From 7e1492c664a23f31051f58f14bfac08f9be86072 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 07:59:15 -0400 Subject: [PATCH] Small improvements. --- SrcMod/Shell/Shell.cs | 2 +- SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs | 9 +- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 99 +++++++++++-------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index bc3aaa7..d353fb2 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Beta 0.4.0"; + public const string Version = "Beta 0.5.0"; public readonly string? ShellDirectory; diff --git a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs index c9b4ced..0369d68 100644 --- a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs +++ b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs @@ -1,10 +1,17 @@ namespace Valve.Miscellaneous; -internal static class TypeParsers +public static class TypeParsers { public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; + public static bool CanParse(Type type) => type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) + || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) + || type == typeof(ulong) || type == typeof(Int128) || type == typeof(UInt128) || type == typeof(nint) + || type == typeof(nuint) || type == typeof(Half) || type == typeof(float) || type == typeof(double) + || type == typeof(decimal) || type == typeof(char) || type == typeof(DateOnly) || type == typeof(DateTime) + || type == typeof(DateTimeOffset) || type == typeof(Guid) || type == typeof(TimeOnly) + || type == typeof(TimeSpan); public static object ParseAll(string msg) { if (TryParse(msg, out sbyte int8)) return int8; diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 4c91189..d4af015 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,5 +1,7 @@ using Valve.Vkv.ObjectModels; +using ValveParsers = Valve.Miscellaneous.TypeParsers; + namespace Valve.Vkv; public static class VkvConvert @@ -68,7 +70,7 @@ public static class VkvConvert } private static object DeserializeObject(string content) => - TypeParsers.ParseAll(content); + ValveParsers.ParseAll(content); private static string DeserializeString(string content, VkvOptions options) { if (options.useQuotes) @@ -118,54 +120,67 @@ public static class VkvConvert { if (node is null) return null; - object? instance = Activator.CreateInstance(outputType); - if (instance is null) return null; - - IEnumerable validFields = from field in outputType.GetFields() - let isPublic = field.IsPublic - let isStatic = field.IsStatic - let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - let isConst = field.IsLiteral - where isPublic && !isStatic && !isIgnored && !isConst - select field; - - IEnumerable validProperties; - if (options.serializeProperties) + if (node is VkvSingleNode single) { - validProperties = from prop in outputType.GetProperties() - let canSet = prop.SetMethod is not null - let isPublic = canSet && prop.SetMethod!.IsPublic - let isStatic = canSet && prop.SetMethod!.IsStatic - let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - where canSet && isPublic && !isStatic && !isIgnored - select prop; - } - else validProperties = Array.Empty(); - - foreach (FieldInfo field in validFields) - { - // TODO: check if the node tree has that field. - - Type castType = field.FieldType; - if (TypeParsers.CanParse(instance)) + object? value = single.value; + if (value is null) return null; + else if (value is string str) { - + value = ValveParsers.ParseAll(str); + if (value is string still && outputType.IsEnum) + { + if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) + value = res; + } } + return Convert.ChangeType(value, outputType); } - foreach (PropertyInfo prop in validProperties) + else if (node is VkvTreeNode tree) { - // TODO: check if the node tree has that field. + object? instance = Activator.CreateInstance(outputType); + if (instance is null) return null; - Type castType = prop.PropertyType; - if (TypeParsers.CanParse(instance)) + IEnumerable validFields = from field in outputType.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties; + if (options.serializeProperties) { - + validProperties = from prop in outputType.GetProperties() + let canSet = prop.SetMethod is not null + let isPublic = canSet && prop.SetMethod!.IsPublic + let isStatic = canSet && prop.SetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + where canSet && isPublic && !isStatic && !isIgnored + select prop; } - } + else validProperties = Array.Empty(); - return null; + foreach (FieldInfo field in validFields) + { + // TODO: check if the node tree has that field. + + // TODO: + // parsables + // enums + // casting + // sub-conversion + } + foreach (PropertyInfo prop in validProperties) + { + // TODO: check if the node tree has that field. + } + + return null; + } + else throw new VkvSerializationException("Unknown VKV node type."); } #endregion @@ -238,12 +253,12 @@ public static class VkvConvert if (obj is null) return null; Type type = obj.GetType(); - if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); + if (type.IsPrimitive || ValveParsers.CanParse(obj)) return new VkvSingleNode(obj); else if (type.IsPointer) throw new("Cannot serialize a pointer."); VkvTreeNode tree = new(); - if (obj is IVkvConvertible vdf) return vdf.ToNodeTree(); + if (obj is IVkvConvertible vkv) return vkv.ToNodeTree(); else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count],