about summary refs log tree commit diff
path: root/LibMatrix/Extensions
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix/Extensions')
-rw-r--r--LibMatrix/Extensions/EnumerableExtensions.cs12
-rw-r--r--LibMatrix/Extensions/JsonElementExtensions.cs148
2 files changed, 154 insertions, 6 deletions
diff --git a/LibMatrix/Extensions/EnumerableExtensions.cs b/LibMatrix/Extensions/EnumerableExtensions.cs

index 4dcf26e..88e79f0 100644 --- a/LibMatrix/Extensions/EnumerableExtensions.cs +++ b/LibMatrix/Extensions/EnumerableExtensions.cs
@@ -4,7 +4,7 @@ using System.Collections.Immutable; namespace LibMatrix.Extensions; public static class EnumerableExtensions { - public static void MergeStateEventLists(this IList<StateEvent> oldState, IList<StateEvent> newState) { + public static void MergeStateEventLists(this IList<MatrixEvent> oldState, IList<MatrixEvent> newState) { // foreach (var stateEvent in newState) { // var old = oldState.FirstOrDefault(x => x.Type == stateEvent.Type && x.StateKey == stateEvent.StateKey); // if (old is null) { @@ -27,7 +27,7 @@ public static class EnumerableExtensions { } } - int FindIndex(StateEvent needle) { + int FindIndex(MatrixEvent needle) { for (int i = 0; i < oldState.Count; i++) { var old = oldState[i]; if (old.Type == needle.Type && old.StateKey == needle.StateKey) @@ -38,7 +38,7 @@ public static class EnumerableExtensions { } } - public static void MergeStateEventLists(this IList<StateEventResponse> oldState, IList<StateEventResponse> newState) { + public static void MergeStateEventLists(this IList<MatrixEventResponse> oldState, IList<MatrixEventResponse> newState) { foreach (var e in newState) { switch (FindIndex(e)) { case -1: @@ -50,7 +50,7 @@ public static class EnumerableExtensions { } } - int FindIndex(StateEventResponse needle) { + int FindIndex(MatrixEventResponse needle) { for (int i = 0; i < oldState.Count; i++) { var old = oldState[i]; if (old.Type == needle.Type && old.StateKey == needle.StateKey) @@ -61,7 +61,7 @@ public static class EnumerableExtensions { } } - public static void MergeStateEventLists(this List<StateEventResponse> oldState, List<StateEventResponse> newState) { + public static void MergeStateEventLists(this List<MatrixEventResponse> oldState, List<MatrixEventResponse> newState) { foreach (var e in newState) { switch (FindIndex(e)) { case -1: @@ -73,7 +73,7 @@ public static class EnumerableExtensions { } } - int FindIndex(StateEventResponse needle) { + int FindIndex(MatrixEventResponse needle) { for (int i = 0; i < oldState.Count; i++) { var old = oldState[i]; if (old.Type == needle.Type && old.StateKey == needle.StateKey) diff --git a/LibMatrix/Extensions/JsonElementExtensions.cs b/LibMatrix/Extensions/JsonElementExtensions.cs
index dfec95b..9225f58 100644 --- a/LibMatrix/Extensions/JsonElementExtensions.cs +++ b/LibMatrix/Extensions/JsonElementExtensions.cs
@@ -0,0 +1,148 @@ +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace LibMatrix.Extensions; + +public static class JsonElementExtensions { + public static bool FindExtraJsonElementFields(this JsonElement obj, Type objectType, string objectPropertyName) { + if (objectPropertyName == "content" && objectType == typeof(JsonObject)) + objectType = typeof(MatrixEventResponse); + // if (t == typeof(JsonNode)) + // return false; + + Console.WriteLine($"{objectType.Name} {objectPropertyName}"); + var unknownPropertyFound = false; + var mappedPropsDict = objectType.GetProperties() + .Where(x => x.GetCustomAttribute<JsonPropertyNameAttribute>() is not null) + .ToDictionary(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()!.Name, x => x); + objectType.GetProperties().Where(x => !mappedPropsDict.ContainsKey(x.Name)) + .ToList().ForEach(x => mappedPropsDict.TryAdd(x.Name, x)); + + foreach (var field in obj.EnumerateObject()) { + if (mappedPropsDict.TryGetValue(field.Name, out var mappedProperty)) { + //dictionary + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { + unknownPropertyFound |= _checkDictionary(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { + unknownPropertyFound |= _checkList(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (field.Name == "content" && (objectType == typeof(MatrixEventResponse) || objectType == typeof(MatrixEvent))) { + unknownPropertyFound |= field.FindExtraJsonPropertyFieldsByValueKind( + MatrixEvent.GetEventType(obj.GetProperty("type").GetString()!), // We expect type to always be present + mappedProperty.PropertyType); + continue; + } + + unknownPropertyFound |= + field.FindExtraJsonPropertyFieldsByValueKind(objectType, mappedProperty.PropertyType); + continue; + } + + Console.WriteLine($"[!!] Unknown property {field.Name} in {objectType.Name}!"); + unknownPropertyFound = true; + } + + return unknownPropertyFound; + } + + private static bool FindExtraJsonPropertyFieldsByValueKind(this JsonProperty field, Type containerType, + Type propertyType) { + if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) propertyType = propertyType.GetGenericArguments()[0]; + + var switchResult = false; + switch (field.Value.ValueKind) { + case JsonValueKind.Array: + switchResult = field.Value.EnumerateArray().Aggregate(switchResult, + (current, element) => current | element.FindExtraJsonElementFields(propertyType, field.Name)); + break; + case JsonValueKind.Object: + switchResult |= field.Value.FindExtraJsonElementFields(propertyType, field.Name); + break; + case JsonValueKind.True: + case JsonValueKind.False: + return _checkBool(field, containerType, propertyType); + case JsonValueKind.String: + return _checkString(field, containerType, propertyType); + case JsonValueKind.Number: + return _checkNumber(field, containerType, propertyType); + case JsonValueKind.Undefined: + case JsonValueKind.Null: + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return switchResult; + } + + private static bool _checkBool(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(bool)) return true; + Console.WriteLine( + $"[!!] Encountered bool for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkString(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(string)) return true; + // ReSharper disable once BuiltInTypeReferenceStyle + if (propertyType == typeof(String)) return true; + Console.WriteLine( + $"[!!] Encountered string for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkNumber(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(int) || + propertyType == typeof(double) || + propertyType == typeof(float) || + propertyType == typeof(decimal) || + propertyType == typeof(long) || + propertyType == typeof(short) || + propertyType == typeof(uint) || + propertyType == typeof(ulong) || + propertyType == typeof(ushort) || + propertyType == typeof(byte) || + propertyType == typeof(sbyte)) + return true; + Console.WriteLine( + $"[!!] Encountered number for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkDictionary(this JsonProperty field, Type containerType, Type propertyType) { + var keyType = propertyType.GetGenericArguments()[0]; + var valueType = propertyType.GetGenericArguments()[1]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!"); + + return field.Value.EnumerateObject() + // TODO: use key.Value? + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType) + ); + } + + private static bool _checkList(this JsonProperty field, Type containerType, Type propertyType) { + var valueType = propertyType.GetGenericArguments()[0]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered list {field.Name} with value type {valueType.Name}!"); + + return field.Value.EnumerateArray() + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonElementFields(valueType, field.Name) + ); + } +} \ No newline at end of file