Finished VKV deserialization development :)

This commit is contained in:
That_One_Nerd 2023-05-10 13:34:22 -04:00
parent c1a90cfc99
commit 7c96f30d1b
2 changed files with 46 additions and 7 deletions

View File

@ -1,7 +1,4 @@
using System; using Valve.Vkv.ObjectModels;
using Valve.Vkv.ObjectModels;
using ValveParsers = Valve.Miscellaneous.TypeParsers;
namespace Valve.Vkv; namespace Valve.Vkv;
@ -115,6 +112,7 @@ public static class VkvConvert
#endregion #endregion
#region FromNodeTree #region FromNodeTree
public static T? FromNodeTree<T>(VkvNode? node, VkvOptions options) => (T?)FromNodeTree(typeof(T), node, options);
public static object? FromNodeTree(Type outputType, VkvNode? node, VkvOptions options) public static object? FromNodeTree(Type outputType, VkvNode? node, VkvOptions options)
{ {
if (node is null) return null; if (node is null) return null;
@ -130,7 +128,7 @@ public static class VkvConvert
if (value is null) return null; if (value is null) return null;
else if (value is string str) else if (value is string str)
{ {
value = ValveParsers.ParseAll(str); value = TypeParsers.ParseAll(str);
if (value is string still && outputType.IsEnum) if (value is string still && outputType.IsEnum)
{ {
if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) if (Enum.TryParse(outputType, still, true, out object? res) && res is not null)
@ -148,6 +146,9 @@ public static class VkvConvert
else if (outputType.GetInterface("IList") is not null) else if (outputType.GetInterface("IList") is not null)
return FromTreeNodeList(outputType, node, options); return FromTreeNodeList(outputType, node, options);
else if (outputType.GetInterface("IDictionary") is not null)
return FromTreeNodeDictionary(outputType, node, options);
object? instance = Activator.CreateInstance(outputType); object? instance = Activator.CreateInstance(outputType);
if (instance is null) return null; if (instance is null) return null;
@ -223,7 +224,7 @@ public static class VkvConvert
// There is no guarentee that the first type argument corresponds to the element type, // There is no guarentee that the first type argument corresponds to the element type,
// but as far as I know there isn't a better way. // but as far as I know there isn't a better way.
Type elementType = outputType.IsGenericType ? outputType.GetGenericArguments().First() : typeof(object); Type elementType = outputType.IsGenericType ? outputType.GenericTypeArguments[0] : typeof(object);
int index = 0; int index = 0;
foreach (KeyValuePair<string, VkvNode?> subNode in node) foreach (KeyValuePair<string, VkvNode?> subNode in node)
@ -235,6 +236,34 @@ public static class VkvConvert
} }
return instance; return instance;
} }
private static object? FromTreeNodeDictionary(Type outputType, VkvTreeNode node, VkvOptions options)
{
IDictionary? instance = (IDictionary?)Activator.CreateInstance(outputType);
if (instance is null) return null;
// There is no guarentee that the first and second type arguments represent the
// key and value types, but as far as I know there isn't a better way.
bool canUseGenerics = outputType.GenericTypeArguments.Length >= 2;
Type keyType = canUseGenerics ? outputType.GenericTypeArguments[0] : typeof(object),
valueType = canUseGenerics ? outputType.GenericTypeArguments[1] : typeof(object);
foreach (KeyValuePair<string, VkvNode?> subNode in node)
{
object key = TypeParsers.ParseAll(subNode.Key);
if (key is string still && keyType.IsEnum)
{
if (Enum.TryParse(keyType, still, true, out object? res) && res is not null)
key = res;
}
key = Convert.ChangeType(key, keyType);
object? value = FromNodeTree(valueType, subNode.Value, options);
instance.Add(key, value);
}
return instance;
}
#endregion #endregion
#region SerializeNode #region SerializeNode
@ -306,7 +335,7 @@ public static class VkvConvert
if (obj is null) return null; if (obj is null) return null;
Type type = obj.GetType(); Type type = obj.GetType();
if (type.IsPrimitive || ValveParsers.CanParse(obj)) return new VkvSingleNode(obj); if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj);
else if (type.IsPointer) throw new("Cannot serialize a pointer."); else if (type.IsPointer) throw new("Cannot serialize a pointer.");
VkvTreeNode tree = new(); VkvTreeNode tree = new();

View File

@ -22,6 +22,16 @@ public class VkvSerializer
if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin);
return result; return result;
} }
public T? Deserialize<T>(Stream stream)
{
VkvNode? result = Deserialize(stream);
return VkvConvert.FromNodeTree<T>(result, p_options);
}
public object? Deserialize(Type outputType, Stream stream)
{
VkvNode? result = Deserialize(stream);
return VkvConvert.FromNodeTree(outputType, result, p_options);
}
public void Serialize(Stream stream, object? value, string parentNodeName) public void Serialize(Stream stream, object? value, string parentNodeName)
{ {