Finished VKV deserialization development :)
This commit is contained in:
parent
c1a90cfc99
commit
7c96f30d1b
@ -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();
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user