diff --git a/Discord.Net.sln b/Discord.Net.sln index a63606787..edc7952fa 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26711.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" EndProject @@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Commands", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.WebSocket", "src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj", "{688FD1D8-7F01-4539-B2E9-F473C5D699C7}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.WS4Net", "src\Discord.Net.Providers.WS4Net\Discord.Net.Providers.WS4Net.csproj", "{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}" @@ -24,6 +22,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests", "test\D EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Webhook", "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj", "{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{1876A445-1C70-4F84-912B-4D3CEA21E0C3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Serialization", "src\Discord.Net.Serialization\Discord.Net.Serialization.csproj", "{AA3B67BE-767E-4230-9810-F7948B6AE689}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -130,6 +132,18 @@ Global {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x64.Build.0 = Release|Any CPU {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.ActiveCfg = Release|Any CPU {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.Build.0 = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x64.Build.0 = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x86.Build.0 = Debug|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|Any CPU.Build.0 = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x64.ActiveCfg = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x64.Build.0 = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x86.ActiveCfg = Release|Any CPU + {AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -139,7 +153,11 @@ Global {5688A353-121E-40A1-8BFA-B17B91FB48FB} = {288C363D-A636-4EAE-9AC1-4698B641B26E} {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} {688FD1D8-7F01-4539-B2E9-F473C5D699C7} = {288C363D-A636-4EAE-9AC1-4698B641B26E} - {6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012} + {6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {1876A445-1C70-4F84-912B-4D3CEA21E0C3} {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} + {AA3B67BE-767E-4230-9810-F7948B6AE689} = {1876A445-1C70-4F84-912B-4D3CEA21E0C3} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9828C525-49C7-48F4-A9E7-94E223052DA2} EndGlobalSection EndGlobal diff --git a/src/Discord.Net.Core/Discord.Net.Core.csproj b/src/Discord.Net.Core/Discord.Net.Core.csproj index adbed2ca0..af4a8a06a 100644 --- a/src/Discord.Net.Core/Discord.Net.Core.csproj +++ b/src/Discord.Net.Core/Discord.Net.Core.csproj @@ -8,6 +8,11 @@ true + + + + + @@ -15,6 +20,6 @@ - + \ No newline at end of file diff --git a/src/Discord.Net.Rest/Discord.Net.Rest.csproj b/src/Discord.Net.Rest/Discord.Net.Rest.csproj index f5b26e181..420387dc1 100644 --- a/src/Discord.Net.Rest/Discord.Net.Rest.csproj +++ b/src/Discord.Net.Rest/Discord.Net.Rest.csproj @@ -9,11 +9,15 @@ + + + + @@ -21,7 +25,4 @@ - - - \ No newline at end of file diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 52bfb6ddf..bfc2293ee 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -4,6 +4,8 @@ using Discord.Net; using Discord.Net.Queue; using Discord.Net.Rest; using Discord.Serialization; +using Discord.Serialization.Json; +using Discord.Serialization.Json.Converters; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -11,6 +13,7 @@ using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Net; +using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.Formatting; @@ -21,13 +24,22 @@ namespace Discord.API { internal class DiscordRestApiClient : IDisposable { + static DiscordRestApiClient() + { + SerializationFormat.Json.AddConverter(); + SerializationFormat.Json.AddConverter(info => info.GetCustomAttribute() != null); + SerializationFormat.Json.AddConverter(info => info.GetCustomAttribute() != null); + SerializationFormat.Json.AddGenericConverter(typeof(EntityOrId<>), typeof(EntityOrIdPropertyConverter<>)); + SerializationFormat.Json.AddGenericConverter(typeof(Optional<>), typeof(OptionalPropertyConverter<>)); + } + private static readonly ConcurrentDictionary> _bucketIdGenerators = new ConcurrentDictionary>(); public event Func SentRequest { add { _sentRequestEvent.Add(value); } remove { _sentRequestEvent.Remove(value); } } private readonly AsyncEvent> _sentRequestEvent = new AsyncEvent>(); protected readonly SemaphoreSlim _stateLock; - protected readonly ScopedSerializer _serializer; + protected readonly Serializer _serializer; protected readonly ConcurrentQueue _formatters; private readonly RestClientProvider _restClientProvider; @@ -44,7 +56,7 @@ namespace Discord.API internal IRestClient RestClient { get; private set; } internal ulong? CurrentUserId { get; set;} - public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, ScopedSerializer serializer, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) + public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, Serializer serializer, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) { _restClientProvider = restClientProvider; UserAgent = userAgent; @@ -1167,13 +1179,13 @@ namespace Discord.API protected static double ToMilliseconds(Stopwatch stopwatch) => Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); protected ReadOnlyBuffer SerializeJson(ArrayFormatter data, object value) { - _serializer.WriteJson(data, value); + _serializer.Write(data, value); return new ReadOnlyBuffer(data.Formatted.Array, 0, data.Formatted.Count); } protected T DeserializeJson(ReadOnlyBuffer data) where T : class, new() { - return _serializer.ReadJson(data); + return _serializer.Read(data); } internal class BucketIds diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs index e71339eff..b49303043 100644 --- a/src/Discord.Net.Rest/DiscordRestClient.cs +++ b/src/Discord.Net.Rest/DiscordRestClient.cs @@ -8,7 +8,7 @@ namespace Discord.Rest { public class DiscordRestClient : BaseDiscordClient, IDiscordClient { - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; private RestApplication _applicationInfo; public new RestSelfUser CurrentUser => base.CurrentUser as RestSelfUser; @@ -16,10 +16,10 @@ namespace Discord.Rest public DiscordRestClient() : this(new DiscordRestConfig()) { } public DiscordRestClient(DiscordRestConfig config) : base(config) { - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _restLogger.WarningAsync("Serializer Error", ex); + _restLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; SetApiClient(new API.DiscordRestApiClient(config.RestClientProvider, DiscordConfig.UserAgent, _serializer, config.DefaultRetryMode)); diff --git a/src/Discord.Net.Rest/Extensions/JsonReaderExtensions.cs b/src/Discord.Net.Rest/Extensions/JsonReaderExtensions.cs deleted file mode 100644 index 1aa7e34a1..000000000 --- a/src/Discord.Net.Rest/Extensions/JsonReaderExtensions.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Text; -using System.Text.Json; -using System.Text.Utf8; - -namespace Discord.Serialization -{ - internal static class JsonReaderExtensions - { - public static bool GetBool(this JsonReader reader) => GetBool(reader.Value); - public static bool GetBool(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseBoolean(text, out bool result, out int ignored, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Boolean"); - } - - public static sbyte GetInt8(this JsonReader reader) => GetInt8(reader.Value); - public static sbyte GetInt8(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseSByte(text, out sbyte result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Int8"); - } - public static short GetInt16(this JsonReader reader) => GetInt16(reader.Value); - public static short GetInt16(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseInt16(text, out short result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Int16"); - } - public static int GetInt32(this JsonReader reader) => GetInt32(reader.Value); - public static int GetInt32(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseInt32(text, out int result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Int32"); - } - public static long GetInt64(this JsonReader reader) => GetInt64(reader.Value); - public static long GetInt64(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseInt64(text, out long result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Int64"); - } - - public static byte GetUInt8(this JsonReader reader) => GetUInt8(reader.Value); - public static byte GetUInt8(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseByte(text, out byte result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse UInt8"); - } - public static ushort GetUInt16(this JsonReader reader) => GetUInt16(reader.Value); - public static ushort GetUInt16(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseUInt16(text, out ushort result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse UInt16"); - } - public static uint GetUInt32(this JsonReader reader) => GetUInt32(reader.Value); - public static uint GetUInt32(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseUInt32(text, out uint result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse UInt32"); - } - public static ulong GetUInt64(this JsonReader reader) => GetUInt64(reader.Value); - public static ulong GetUInt64(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseUInt64(text, out ulong result, out int ignored, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse UInt64"); - } - - public static char GetChar(this JsonReader reader) => GetChar(reader.Value); - public static char GetChar(this ReadOnlySpan text) - { - string str = GetString(text); - if (str.Length == 1) - return str[0]; - throw new SerializationException("Failed to parse Char"); - } - public static string GetString(this JsonReader reader) => GetString(reader.Value); - public static string GetString(this ReadOnlySpan text) => new Utf8String(text).ToString(); - - public static float GetSingle(this JsonReader reader) => GetSingle(reader.Value); - public static float GetSingle(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) - return (float)result; - throw new SerializationException("Failed to parse Single"); - } - public static double GetDouble(this JsonReader reader) => GetDouble(reader.Value); - public static double GetDouble(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) - return (double)result; - throw new SerializationException("Failed to parse Double"); - } - public static decimal GetDecimal(this JsonReader reader) => GetDecimal(reader.Value); - public static decimal GetDecimal(this ReadOnlySpan text) - { - if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) - return result; - throw new SerializationException("Failed to parse Decimal"); - } - - public static DateTime GetDateTime(this JsonReader reader) => GetDateTime(reader.Value); - public static DateTime GetDateTime(this ReadOnlySpan text) - { - string str = GetString(text); - if (DateTime.TryParse(str, out var result)) //TODO: Improve perf - return result; - throw new SerializationException("Failed to parse DateTime"); - } - public static DateTimeOffset GetDateTimeOffset(this JsonReader reader) => GetDateTimeOffset(reader.Value); - public static DateTimeOffset GetDateTimeOffset(this ReadOnlySpan text) - { - string str = GetString(text); - if (DateTimeOffset.TryParse(str, out var result)) //TODO: Improve perf - return result; - throw new SerializationException("Failed to parse DateTimeOffset"); - } - - public static void Skip(this JsonReader reader) - { - int initialDepth = reader._depth; - while (reader.Read() && reader._depth > initialDepth) { } - } - } -} diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs index 9cd834e32..6fd212eed 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs @@ -104,7 +104,7 @@ namespace Discord.Net.Queue { try { - var error = Serializer.ReadJson(response.Data); + var error = Serializer.Json.Read(response.Data); code = error.Code; reason = error.Message; } diff --git a/src/Discord.Net.Rest/Serialization/Converters/ArrayPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/ArrayPropertyConverter.cs deleted file mode 100644 index 0e0ee5bfb..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/ArrayPropertyConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class ArrayPropertyConverter : IPropertyConverter - { - private readonly IPropertyConverter _innerConverter; - - public ArrayPropertyConverter(IPropertyConverter innerConverter) - { - _innerConverter = innerConverter; - } - - public T[] ReadJson(JsonReader reader, bool read = true) - { - if ((read && !reader.Read()) || reader.TokenType != JsonTokenType.StartArray) - throw new SerializationException("Bad input, expected StartArray"); - - var list = new List(); - while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) - list.Add(_innerConverter.ReadJson(reader)); - return list.ToArray(); - } - - public void WriteJson(JsonWriter writer, T[] value) - { - writer.WriteArrayStart(); - for (int i = 0; i < value.Length; i++) - _innerConverter.WriteJson(writer, value[i]); - writer.WriteArrayEnd(); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Converter.cs b/src/Discord.Net.Rest/Serialization/Converters/Converter.cs deleted file mode 100644 index 9a15ad3a3..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Converter.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Discord.API; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Discord.Serialization.Converters -{ - internal static class Converter - { - private static readonly MethodInfo _makeListConverterFunc - = typeof(Converter).GetTypeInfo().GetDeclaredMethod(nameof(MakeListConverterInternal)); - private static readonly MethodInfo _makeOptionalConverterFunc - = typeof(Converter).GetTypeInfo().GetDeclaredMethod(nameof(MakeOptionalConverterInternal)); - private static readonly MethodInfo _makeNullableConverterFunc - = typeof(Converter).GetTypeInfo().GetDeclaredMethod(nameof(MakeNullableConverterInternal)); - private static readonly MethodInfo _makeEntityOrIdConverterFunc - = typeof(Converter).GetTypeInfo().GetDeclaredMethod(nameof(MakeEntityOrIdConverterInternal)); - - public static IPropertyConverter For() - => (IPropertyConverter)ForInternal(); - private static object ForInternal() - { - var typeInfo = typeof(TProp).GetTypeInfo(); - - //Generics - if (typeof(TProp).IsConstructedGenericType) - { - Type genericType = typeof(TProp).GetGenericTypeDefinition(); - if (genericType == typeof(List<>)) - return MakeListConverter(typeof(TProp).GenericTypeArguments[0]); - else if (genericType == typeof(Optional<>)) - return MakeOptionalConverter(typeof(TProp).GenericTypeArguments[0]); - else if (genericType == typeof(Nullable<>)) - return MakeNullableConverter(typeof(TProp).GenericTypeArguments[0]); - else if (genericType == typeof(EntityOrId<>)) - return MakeEntityOrIdConverter(typeof(TProp).GenericTypeArguments[0]); - } - - //Enums - if (typeInfo.IsEnum) return new EnumPropertyConverter(); - - //Primitives - if (typeof(TProp) == typeof(bool)) return new BooleanPropertyConverter(); - - if (typeof(TProp) == typeof(sbyte)) return new Int8PropertyConverter(); - if (typeof(TProp) == typeof(short)) return new Int16PropertyConverter(); - if (typeof(TProp) == typeof(int)) return new Int32PropertyConverter(); - if (typeof(TProp) == typeof(long)) - { - if (typeInfo.GetCustomAttribute() != null) - return new Int53PropertyConverter(); - else - return new Int64PropertyConverter(); - } - - if (typeof(TProp) == typeof(byte)) return new UInt8PropertyConverter(); - if (typeof(TProp) == typeof(ushort)) return new UInt16PropertyConverter(); - if (typeof(TProp) == typeof(uint)) return new UInt32PropertyConverter(); - if (typeof(TProp) == typeof(ulong)) - { - if (typeInfo.GetCustomAttribute() != null) - return new UInt53PropertyConverter(); - else - return new UInt64PropertyConverter(); - } - - if (typeof(TProp) == typeof(float)) return new SinglePropertyConverter(); - if (typeof(TProp) == typeof(double)) return new DoublePropertyConverter(); - if (typeof(TProp) == typeof(decimal)) return new DecimalPropertyConverter(); - - if (typeof(TProp) == typeof(char)) return new CharPropertyConverter(); - if (typeof(TProp) == typeof(string)) return new StringPropertyConverter(); - - //Structs - if (typeof(TProp) == typeof(DateTime)) return new DateTimePropertyConverter(); - if (typeof(TProp) == typeof(DateTimeOffset)) return new DateTimeOffsetPropertyConverter(); - if (typeof(TProp) == typeof(Image)) return new ImagePropertyConverter(); - - throw new InvalidOperationException($"Unsupported model type: {typeof(TProp).Name}"); - } - - private static IPropertyConverter MakeListConverter(Type innerType) - => _makeListConverterFunc.MakeGenericMethod(innerType).Invoke(null, null) as IPropertyConverter; - private static IPropertyConverter> MakeListConverterInternal() - => new ListPropertyConverter(For()); - - private static IPropertyConverter MakeOptionalConverter(Type innerType) - => _makeOptionalConverterFunc.MakeGenericMethod(innerType).Invoke(null, null) as IPropertyConverter; - private static IPropertyConverter> MakeOptionalConverterInternal() - => new OptionalPropertyConverter(For()); - - private static IPropertyConverter MakeNullableConverter(Type innerType) - => _makeNullableConverterFunc.MakeGenericMethod(innerType).Invoke(null, null) as IPropertyConverter; - private static IPropertyConverter MakeNullableConverterInternal() - where TInnerProp : struct - => new NullablePropertyConverter(For()); - - private static IPropertyConverter MakeEntityOrIdConverter(Type innerType) - => _makeEntityOrIdConverterFunc.MakeGenericMethod(innerType).Invoke(null, null) as IPropertyConverter; - private static IPropertyConverter> MakeEntityOrIdConverterInternal() - => new EntityOrIdPropertyConverter(For()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/EntityOrIdPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/EntityOrIdPropertyConverter.cs deleted file mode 100644 index 6af9f98eb..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/EntityOrIdPropertyConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Discord.API; -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class EntityOrIdPropertyConverter : IPropertyConverter> - { - private readonly IPropertyConverter _innerConverter; - - public EntityOrIdPropertyConverter(IPropertyConverter innerConverter) - { - _innerConverter = innerConverter; - } - - public EntityOrId ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType == JsonValueType.Number) - return new EntityOrId(reader.GetUInt64()); - return new EntityOrId(_innerConverter.ReadJson(reader)); - } - - public void WriteJson(JsonWriter writer, EntityOrId value) - { - if (value.Object != null) - _innerConverter.WriteJson(writer, value.Object); - else - writer.WriteValue(value.Id); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/EnumPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/EnumPropertyConverter.cs deleted file mode 100644 index 3b6f94dcb..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/EnumPropertyConverter.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class EnumPropertyConverter : IPropertyConverter - { - public T ReadJson(JsonReader reader, bool read = true) - => throw new System.NotImplementedException(); - public void WriteJson(JsonWriter writer, T value) - => throw new System.NotImplementedException(); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/IPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/IPropertyConverter.cs deleted file mode 100644 index bd6d5d552..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/IPropertyConverter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal interface IPropertyConverter - { - T ReadJson(JsonReader reader, bool read = true); - void WriteJson(JsonWriter writer, T value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/ImagePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/ImagePropertyConverter.cs deleted file mode 100644 index f94a68cd4..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/ImagePropertyConverter.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class ImagePropertyConverter : IPropertyConverter - { - public Image ReadJson(JsonReader reader, bool read = true) - => throw new System.NotImplementedException(); - public void WriteJson(JsonWriter writer, Image value) - => throw new System.NotImplementedException(); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/NullablePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/NullablePropertyConverter.cs deleted file mode 100644 index 9be9b984e..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/NullablePropertyConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class NullablePropertyConverter : IPropertyConverter - where T : struct - { - private readonly IPropertyConverter _innerConverter; - - public NullablePropertyConverter(IPropertyConverter innerConverter) - { - _innerConverter = innerConverter; - } - - public T? ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType == JsonValueType.Null) - return null; - return _innerConverter.ReadJson(reader); - } - - public void WriteJson(JsonWriter writer, T? value) - { - if (value.HasValue) - _innerConverter.WriteJson(writer, value.Value); - else - writer.WriteNull(); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/OptionalPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/OptionalPropertyConverter.cs deleted file mode 100644 index 608fd5144..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/OptionalPropertyConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class OptionalPropertyConverter : IPropertyConverter> - { - private readonly IPropertyConverter _innerConverter; - - public OptionalPropertyConverter(IPropertyConverter innerConverter) - { - _innerConverter = innerConverter; - } - - public Optional ReadJson(JsonReader reader, bool read = true) - => new Optional(_innerConverter.ReadJson(reader, read)); - - public void WriteJson(JsonWriter writer, Optional value) - { - if (value.IsSpecified) - _innerConverter.WriteJson(writer, value.Value); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/CharPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/CharPropertyConverter.cs deleted file mode 100644 index 23aaa88aa..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/CharPropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class CharPropertyConverter : IPropertyConverter - { - public char ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetChar(); - } - public void WriteJson(JsonWriter writer, char value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimeOffsetPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimeOffsetPropertyConverter.cs deleted file mode 100644 index e484a9196..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimeOffsetPropertyConverter.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class DateTimeOffsetPropertyConverter : IPropertyConverter - { - public DateTimeOffset ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetDateTimeOffset(); - } - public void WriteJson(JsonWriter writer, DateTimeOffset value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimePropertyConverter.cs deleted file mode 100644 index 7ddb39084..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DateTimePropertyConverter.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class DateTimePropertyConverter : IPropertyConverter - { - public DateTime ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetDateTime(); - } - public void WriteJson(JsonWriter writer, DateTime value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DecimalPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/DecimalPropertyConverter.cs deleted file mode 100644 index 786d12ebe..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DecimalPropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class DecimalPropertyConverter : IPropertyConverter - { - public decimal ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetDecimal(); - } - public void WriteJson(JsonWriter writer, decimal value) - => writer.WriteValue(value.ToString()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DoublePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/DoublePropertyConverter.cs deleted file mode 100644 index 87590464d..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/DoublePropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class DoublePropertyConverter : IPropertyConverter - { - public double ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetDouble(); - } - public void WriteJson(JsonWriter writer, double value) - => writer.WriteValue(value.ToString()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int16PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int16PropertyConverter.cs deleted file mode 100644 index a80137878..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int16PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class Int16PropertyConverter : IPropertyConverter - { - public short ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetInt16(); - } - public void WriteJson(JsonWriter writer, short value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int32PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int32PropertyConverter.cs deleted file mode 100644 index af189753d..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int32PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class Int32PropertyConverter : IPropertyConverter - { - public int ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetInt32(); - } - public void WriteJson(JsonWriter writer, int value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int64PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int64PropertyConverter.cs deleted file mode 100644 index ad6dec00a..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int64PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class Int64PropertyConverter : IPropertyConverter - { - public long ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetInt64(); - } - public void WriteJson(JsonWriter writer, long value) - => writer.WriteValue(value.ToString()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int8PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int8PropertyConverter.cs deleted file mode 100644 index de725d531..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int8PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class Int8PropertyConverter : IPropertyConverter - { - public sbyte ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetInt8(); - } - public void WriteJson(JsonWriter writer, sbyte value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/SinglePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/SinglePropertyConverter.cs deleted file mode 100644 index 222ae8683..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/SinglePropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class SinglePropertyConverter : IPropertyConverter - { - public float ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetSingle(); - } - public void WriteJson(JsonWriter writer, float value) - => writer.WriteValue(value.ToString()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/StringPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/StringPropertyConverter.cs deleted file mode 100644 index 328adb885..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/StringPropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class StringPropertyConverter : IPropertyConverter - { - public string ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetString(); - } - public void WriteJson(JsonWriter writer, string value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt16PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt16PropertyConverter.cs deleted file mode 100644 index 2bb0bee85..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt16PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class UInt16PropertyConverter : IPropertyConverter - { - public ushort ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetUInt16(); - } - public void WriteJson(JsonWriter writer, ushort value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt32PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt32PropertyConverter.cs deleted file mode 100644 index a55f23804..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt32PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class UInt32PropertyConverter : IPropertyConverter - { - public uint ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetUInt32(); - } - public void WriteJson(JsonWriter writer, uint value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt64PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt64PropertyConverter.cs deleted file mode 100644 index 07eec7ea3..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt64PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class UInt64PropertyConverter : IPropertyConverter - { - public ulong ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.String) - throw new SerializationException("Bad input, expected String"); - return reader.GetUInt64(); - } - public void WriteJson(JsonWriter writer, ulong value) - => writer.WriteValue(value.ToString()); - } -} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt8PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt8PropertyConverter.cs deleted file mode 100644 index af62d8c05..000000000 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt8PropertyConverter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Text.Json; - -namespace Discord.Serialization.Converters -{ - internal class UInt8PropertyConverter : IPropertyConverter - { - public byte ReadJson(JsonReader reader, bool read = true) - { - if (read) - reader.Read(); - if (reader.ValueType != JsonValueType.Number) - throw new SerializationException("Bad input, expected Number"); - return reader.GetUInt8(); - } - public void WriteJson(JsonWriter writer, byte value) - => writer.WriteValue(value); - } -} diff --git a/src/Discord.Net.Rest/Serialization/JsonConverters/EntityOrIdPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/JsonConverters/EntityOrIdPropertyConverter.cs new file mode 100644 index 000000000..4eeab4ca3 --- /dev/null +++ b/src/Discord.Net.Rest/Serialization/JsonConverters/EntityOrIdPropertyConverter.cs @@ -0,0 +1,32 @@ +using Discord.API; +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class EntityOrIdPropertyConverter : IJsonPropertyConverter> + { + private readonly IJsonPropertyConverter _innerConverter; + + public EntityOrIdPropertyConverter(IJsonPropertyConverter innerConverter) + { + _innerConverter = innerConverter; + } + + public EntityOrId Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType == JsonValueType.Number) + return new EntityOrId(reader.ParseUInt64()); + return new EntityOrId(_innerConverter.Read(reader)); + } + + public void Write(JsonWriter writer, EntityOrId value) + { + if (value.Object != null) + _innerConverter.Write(writer, value.Object); + else + writer.WriteValue(value.Id); + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/JsonConverters/ImagePropertyConverter.cs b/src/Discord.Net.Rest/Serialization/JsonConverters/ImagePropertyConverter.cs new file mode 100644 index 000000000..af3fcd76e --- /dev/null +++ b/src/Discord.Net.Rest/Serialization/JsonConverters/ImagePropertyConverter.cs @@ -0,0 +1,12 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class ImagePropertyConverter : IJsonPropertyConverter + { + public API.Image Read(JsonReader reader, bool read = true) + => throw new System.NotImplementedException(); + public void Write(JsonWriter writer, API.Image value) + => throw new System.NotImplementedException(); + } +} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int53PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/JsonConverters/Int53PropertyConverter.cs similarity index 51% rename from src/Discord.Net.Rest/Serialization/Converters/Primitives/Int53PropertyConverter.cs rename to src/Discord.Net.Rest/Serialization/JsonConverters/Int53PropertyConverter.cs index d8bbd64fc..e8006a33e 100644 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/Int53PropertyConverter.cs +++ b/src/Discord.Net.Rest/Serialization/JsonConverters/Int53PropertyConverter.cs @@ -1,18 +1,18 @@ using System.Text.Json; -namespace Discord.Serialization.Converters +namespace Discord.Serialization.Json.Converters { - internal class Int53PropertyConverter : IPropertyConverter + internal class Int53PropertyConverter : IJsonPropertyConverter { - public long ReadJson(JsonReader reader, bool read = true) + public long Read(JsonReader reader, bool read = true) { if (read) reader.Read(); if (reader.ValueType != JsonValueType.Number) throw new SerializationException("Bad input, expected Number"); - return reader.GetInt64(); + return reader.ParseInt64(); } - public void WriteJson(JsonWriter writer, long value) + public void Write(JsonWriter writer, long value) => writer.WriteValue(value); } } diff --git a/src/Discord.Net.Rest/Serialization/JsonConverters/OptionalPropertyConverter.cs b/src/Discord.Net.Rest/Serialization/JsonConverters/OptionalPropertyConverter.cs new file mode 100644 index 000000000..82dc700ab --- /dev/null +++ b/src/Discord.Net.Rest/Serialization/JsonConverters/OptionalPropertyConverter.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class OptionalPropertyConverter : IJsonPropertyConverter> + { + private readonly IJsonPropertyConverter _innerConverter; + + public OptionalPropertyConverter(IJsonPropertyConverter innerConverter) + { + _innerConverter = innerConverter; + } + + public Optional Read(JsonReader reader, bool read = true) + => new Optional(_innerConverter.Read(reader, read)); + + public void Write(JsonWriter writer, Optional value) + { + if (value.IsSpecified) + _innerConverter.Write(writer, value.Value); + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt53PropertyConverter.cs b/src/Discord.Net.Rest/Serialization/JsonConverters/UInt53PropertyConverter.cs similarity index 50% rename from src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt53PropertyConverter.cs rename to src/Discord.Net.Rest/Serialization/JsonConverters/UInt53PropertyConverter.cs index 49502ce5e..5dd482fe9 100644 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/UInt53PropertyConverter.cs +++ b/src/Discord.Net.Rest/Serialization/JsonConverters/UInt53PropertyConverter.cs @@ -1,18 +1,18 @@ using System.Text.Json; -namespace Discord.Serialization.Converters +namespace Discord.Serialization.Json.Converters { - internal class UInt53PropertyConverter : IPropertyConverter + internal class UInt53PropertyConverter : IJsonPropertyConverter { - public ulong ReadJson(JsonReader reader, bool read = true) + public ulong Read(JsonReader reader, bool read = true) { if (read) reader.Read(); if (reader.ValueType != JsonValueType.Number) throw new SerializationException("Bad input, expected Number"); - return reader.GetUInt64(); + return reader.ParseUInt64(); } - public void WriteJson(JsonWriter writer, ulong value) + public void Write(JsonWriter writer, ulong value) => writer.WriteValue(value); } } diff --git a/src/Discord.Net.Rest/Serialization/ModelMap.cs b/src/Discord.Net.Rest/Serialization/ModelMap.cs deleted file mode 100644 index 737a470a7..000000000 --- a/src/Discord.Net.Rest/Serialization/ModelMap.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.Json; - -namespace Discord.Serialization -{ - internal static class ModelMap - { - private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); - - internal static ModelMap For() - where T : class, new() - { - return _cache.GetOrAdd(typeof(T), _ => - { - var type = typeof(T).GetTypeInfo(); - var properties = new Dictionary>(); - - var propInfos = type.DeclaredProperties.ToArray(); - for (int i = 0; i < propInfos.Length; i++) - { - var propInfo = propInfos[i]; - if (!propInfo.CanRead || !propInfo.CanWrite) - continue; - - var propMap = PropertyMap.Create(propInfo); - properties.Add(propMap.Key, propMap); - } - - return new ModelMap(properties); - }) as ModelMap; - } - } - - internal class ModelMap - where T : class, new() - { - private readonly PropertyMap[] _propertyList; - private readonly Dictionary> _properties; - - public ModelMap(Dictionary> properties) - { - _properties = properties; - _propertyList = _properties.Values.ToArray(); - } - - public T ReadJson(JsonReader reader) - { - var model = new T(); - - if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) - throw new InvalidOperationException("Bad input, expected StartObject"); - while (reader.Read()) - { - if (reader.TokenType == JsonTokenType.EndObject) - return model; - if (reader.TokenType != JsonTokenType.PropertyName) - throw new InvalidOperationException("Bad input, expected PropertyName"); - - string key = reader.GetString(); - if (_properties.TryGetValue(key, out var property)) - property.ReadJson(model, reader); - else - reader.Skip(); //Unknown property, skip - - if (!reader.Read()) - throw new InvalidOperationException("Bad input, expected Value"); - } - throw new InvalidOperationException("Bad input, expected EndObject"); - } - public void WriteJson(T model, JsonWriter writer) - { - writer.WriteObjectStart(); - for (int i = 0; i < _propertyList.Length; i++) - { - var property = _propertyList[i]; - writer.WriteStartAttribute(property.Key); - property.WriteJson(model, writer); - } - writer.WriteObjectEnd(); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/PropertyMap.cs b/src/Discord.Net.Rest/Serialization/PropertyMap.cs deleted file mode 100644 index 0ac7057a2..000000000 --- a/src/Discord.Net.Rest/Serialization/PropertyMap.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Discord.Serialization.Converters; -using System; -using System.Reflection; -using System.Text.Json; - -namespace Discord.Serialization -{ - internal static class PropertyMap - { - public static PropertyMap Create(PropertyInfo propInfo) - { - var type = typeof(PropertyMap<,>).MakeGenericType(typeof(TModel), propInfo.PropertyType); - return Activator.CreateInstance(type, propInfo) as PropertyMap; - } - } - - internal abstract class PropertyMap - { - public string Key { get; protected set; } - - public abstract void WriteJson(TModel model, JsonWriter writer); - public abstract void ReadJson(TModel model, JsonReader reader); - } - - internal class PropertyMap : PropertyMap - { - private readonly IPropertyConverter _converter; - private readonly Func _getFunc; - private readonly Action _setFunc; - - public PropertyMap(PropertyInfo propInfo) - { - var jsonProperty = propInfo.GetCustomAttribute(); - if (jsonProperty != null) - Key = jsonProperty.Key; - else - Key = propInfo.Name; - - _getFunc = propInfo.GetMethod.CreateDelegate(typeof(Func)) as Func; - _setFunc = propInfo.SetMethod.CreateDelegate(typeof(Action)) as Action; - - _converter = Converter.For(); - } - - private TProp GetValue(TModel model) - => _getFunc(model); - private void SetValue(TModel model, TProp prop) - => _setFunc(model, prop); - - public override void WriteJson(TModel model, JsonWriter writer) - { - var value = GetValue(model); - _converter.WriteJson(writer, value); - } - public override void ReadJson(TModel model, JsonReader reader) - { - var value = _converter.ReadJson(reader); - SetValue(model, value); - } - } -} diff --git a/src/Discord.Net.Rest/Serialization/Serializer.cs b/src/Discord.Net.Rest/Serialization/Serializer.cs deleted file mode 100644 index d205bb84d..000000000 --- a/src/Discord.Net.Rest/Serialization/Serializer.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Text; -using System.Text.Formatting; -using System.Text.Json; -using System.Threading.Tasks; - -namespace Discord.Serialization -{ - internal class Serializer - { - public static ScopedSerializer Global { get; } = new ScopedSerializer(); - - public static T ReadJson(ReadOnlyBuffer data) where T : class, new() => Global.ReadJson(data); - public static void WriteJson(ArrayFormatter data, T obj) where T : class, new() => Global.WriteJson(data, obj); - - public static ScopedSerializer CreateScope() => new ScopedSerializer(); - } - - internal class ScopedSerializer - { - private readonly AsyncEvent> _errorEvent = new AsyncEvent>(); - public event Func Error - { - add { _errorEvent.Add(value); } - remove { _errorEvent.Remove(value); } - } - - public T ReadJson(ReadOnlyBuffer data) - where T : class, new() - => ModelMap.For().ReadJson(new JsonReader(data.Span, SymbolTable.InvariantUtf8)); - public void WriteJson(ArrayFormatter data, T obj) - where T : class, new() - => ModelMap.For().WriteJson(obj, new JsonWriter(data)); - } -} diff --git a/src/Discord.Net.Rpc/DiscordRpcApiClient.cs b/src/Discord.Net.Rpc/DiscordRpcApiClient.cs index f669fc642..34eb1efd3 100644 --- a/src/Discord.Net.Rpc/DiscordRpcApiClient.cs +++ b/src/Discord.Net.Rpc/DiscordRpcApiClient.cs @@ -41,11 +41,11 @@ namespace Discord.API } public Task SetResultAsync(ReadOnlyBuffer data) { - return Promise.TrySetResultAsync(Serializer.ReadJson(data)); + return Promise.TrySetResultAsync(Serializer.Json.Read(data)); } public Task SetExceptionAsync(ReadOnlyBuffer data) { - var error = Serializer.ReadJson(data); + var error = Serializer.Json.Read(data); return Promise.TrySetExceptionAsync(new RpcException(error.Code, error.Message)); } } @@ -72,7 +72,7 @@ namespace Discord.API public ConnectionState ConnectionState { get; private set; } public DiscordRpcApiClient(string clientId, string userAgent, string origin, RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, - ScopedSerializer serializer, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) + Serializer serializer, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) : base(restClientProvider, userAgent, serializer, defaultRetryMode) { _connectionLock = new SemaphoreSlim(1, 1); @@ -99,7 +99,7 @@ namespace Discord.API _decompressionStream.SetLength(_decompressionStream.Position); _decompressionStream.Position = 0; - var msg = _serializer.ReadJson(_decompressionStream.ToReadOnlyBuffer()); + var msg = _serializer.Read(_decompressionStream.ToReadOnlyBuffer()); if (msg != null) { await _receivedRpcEvent.InvokeAsync(msg.Cmd, msg.Event, msg.Data).ConfigureAwait(false); @@ -110,7 +110,7 @@ namespace Discord.API } else { - var msg = _serializer.ReadJson(data); + var msg = _serializer.Read(data); if (msg != null) { await _receivedRpcEvent.InvokeAsync(msg.Cmd, msg.Event, msg.Data).ConfigureAwait(false); diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.cs b/src/Discord.Net.Rpc/DiscordRpcClient.cs index ac34ab81f..2615972f9 100644 --- a/src/Discord.Net.Rpc/DiscordRpcClient.cs +++ b/src/Discord.Net.Rpc/DiscordRpcClient.cs @@ -16,7 +16,7 @@ namespace Discord.Rpc private readonly ConnectionManager _connection; private readonly Logger _rpcLogger; private readonly SemaphoreSlim _stateLock, _authorizeLock; - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; public ConnectionState ConnectionState { get; private set; } public IReadOnlyCollection Scopes { get; private set; } @@ -37,10 +37,10 @@ namespace Discord.Rpc _authorizeLock = new SemaphoreSlim(1, 1); _rpcLogger = LogManager.CreateLogger("RPC"); - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _rpcLogger.WarningAsync("Serializer Error", ex); + _rpcLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; SetApiClient(new API.DiscordRpcApiClient(clientId, DiscordRestConfig.UserAgent, origin, config.RestClientProvider, config.WebSocketProvider, _serializer)); @@ -293,7 +293,7 @@ namespace Discord.Rpc case "READY": { await _rpcLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var options = new RequestOptions { @@ -335,7 +335,7 @@ namespace Discord.Rpc case "CHANNEL_CREATE": { await _rpcLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var channel = RpcChannelSummary.Create(data); await _channelCreatedEvent.InvokeAsync(channel).ConfigureAwait(false); @@ -346,7 +346,7 @@ namespace Discord.Rpc case "GUILD_CREATE": { await _rpcLogger.DebugAsync("Received Dispatch (GUILD_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var guild = RpcGuildSummary.Create(data); await _guildCreatedEvent.InvokeAsync(guild).ConfigureAwait(false); @@ -355,7 +355,7 @@ namespace Discord.Rpc case "GUILD_STATUS": { await _rpcLogger.DebugAsync("Received Dispatch (GUILD_STATUS)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var guildStatus = RpcGuildStatus.Create(data); await _guildStatusUpdatedEvent.InvokeAsync(guildStatus).ConfigureAwait(false); @@ -366,7 +366,7 @@ namespace Discord.Rpc case "VOICE_STATE_CREATE": { await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var voiceState = RpcVoiceState.Create(this, data); await _voiceStateCreatedEvent.InvokeAsync(voiceState).ConfigureAwait(false); @@ -375,7 +375,7 @@ namespace Discord.Rpc case "VOICE_STATE_UPDATE": { await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var voiceState = RpcVoiceState.Create(this, data); await _voiceStateUpdatedEvent.InvokeAsync(voiceState).ConfigureAwait(false); @@ -384,7 +384,7 @@ namespace Discord.Rpc case "VOICE_STATE_DELETE": { await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_DELETE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var voiceState = RpcVoiceState.Create(this, data); await _voiceStateDeletedEvent.InvokeAsync(voiceState).ConfigureAwait(false); @@ -394,7 +394,7 @@ namespace Discord.Rpc case "SPEAKING_START": { await _rpcLogger.DebugAsync("Received Dispatch (SPEAKING_START)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); await _speakingStartedEvent.InvokeAsync(data.UserId).ConfigureAwait(false); } @@ -402,7 +402,7 @@ namespace Discord.Rpc case "SPEAKING_STOP": { await _rpcLogger.DebugAsync("Received Dispatch (SPEAKING_STOP)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); await _speakingStoppedEvent.InvokeAsync(data.UserId).ConfigureAwait(false); } @@ -410,7 +410,7 @@ namespace Discord.Rpc case "VOICE_SETTINGS_UPDATE": { await _rpcLogger.DebugAsync("Received Dispatch (VOICE_SETTINGS_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var settings = VoiceSettings.Create(data); await _voiceSettingsUpdated.InvokeAsync(settings).ConfigureAwait(false); @@ -421,7 +421,7 @@ namespace Discord.Rpc case "MESSAGE_CREATE": { await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var msg = RpcMessage.Create(this, data.ChannelId, data.Message); await _messageReceivedEvent.InvokeAsync(msg).ConfigureAwait(false); @@ -430,7 +430,7 @@ namespace Discord.Rpc case "MESSAGE_UPDATE": { await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); var msg = RpcMessage.Create(this, data.ChannelId, data.Message); await _messageUpdatedEvent.InvokeAsync(msg).ConfigureAwait(false); @@ -439,7 +439,7 @@ namespace Discord.Rpc case "MESSAGE_DELETE": { await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload.Value); + var data = _serializer.Read(payload.Value); await _messageDeletedEvent.InvokeAsync(data.ChannelId, data.Message.Id).ConfigureAwait(false); } diff --git a/src/Discord.Net.Serialization/ConverterCollection.cs b/src/Discord.Net.Serialization/ConverterCollection.cs new file mode 100644 index 000000000..71c416589 --- /dev/null +++ b/src/Discord.Net.Serialization/ConverterCollection.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Reflection; + +namespace Discord.Serialization +{ + public class ConverterCollection + { + private class ConverterTypeCollection + { + public Type DefaultConverterType; + public List<(Func Condition, Type ConverterType)> Conditionals = new List<(Func, Type)>(); + } + + private static readonly MethodInfo _getConverterMethod + = typeof(ConverterCollection).GetTypeInfo().GetDeclaredMethod(nameof(Get)); + + private readonly ConcurrentDictionary _maps = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _types = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _genericTypes = new ConcurrentDictionary(); + + internal ConverterCollection() { } + + public void Add() + { + var converters = _types.GetOrAdd(typeof(TType), _ => new ConverterTypeCollection()); + converters.DefaultConverterType = typeof(TConverter); + } + public void Add(Func condition) + { + var converters = _types.GetOrAdd(typeof(TType), _ => new ConverterTypeCollection()); + converters.Conditionals.Add((condition, typeof(TConverter))); + } + + public void AddGeneric(Type openType, Type openConverterType) + { + if (openType.IsConstructedGenericType) throw new InvalidOperationException($"{nameof(openType)} must be an open generic"); + if (openConverterType.IsConstructedGenericType) throw new InvalidOperationException($"{nameof(openConverterType)} must be an open generic"); + var converters = _genericTypes.GetOrAdd(openType, _ => new ConverterTypeCollection()); + converters.DefaultConverterType = openConverterType; + } + public void AddGeneric(Type openType, Type openConverterType, Func condition) + { + if (openType.IsConstructedGenericType) throw new InvalidOperationException($"{nameof(openType)} must be an open generic"); + if (openConverterType.IsConstructedGenericType) throw new InvalidOperationException($"{nameof(openConverterType)} must be an open generic"); + var converters = _genericTypes.GetOrAdd(openType, _ => new ConverterTypeCollection()); + converters.Conditionals.Add((condition, openConverterType)); + } + + public object Get(PropertyInfo propInfo) + { + var typeInfo = typeof(TType).GetTypeInfo(); + + //Generic converters + if (typeInfo.IsGenericType) + { + var converterType = FindConverterType(typeInfo.GetGenericTypeDefinition(), _genericTypes, propInfo); + if (converterType != null) + { + var innerType = typeInfo.GenericTypeArguments[0]; + converterType = converterType.MakeGenericType(innerType); + object innerConverter = GetInnerConverter(innerType, propInfo); + return Activator.CreateInstance(converterType, innerConverter); + } + } + + //Normal converters + { + var converterType = FindConverterType(typeof(TType), _types, propInfo); + if (converterType != null) + return Activator.CreateInstance(converterType); + } + + throw new InvalidOperationException($"Unsupported model type: {typeof(TType).Name}"); + } + private object GetInnerConverter(Type type, PropertyInfo propInfo) + => _getConverterMethod.MakeGenericMethod(type).Invoke(this, new object[] { propInfo }); + + private Type FindConverterType(Type type, ConcurrentDictionary collection, PropertyInfo propInfo) + { + if (collection.TryGetValue(type, out var converters)) + { + for (int i = 0; i < converters.Conditionals.Count; i++) + { + if (converters.Conditionals[i].Condition(propInfo)) + return converters.Conditionals[i].ConverterType; + } + if (converters.DefaultConverterType != null) + return converters.DefaultConverterType; + } + return null; + } + } +} diff --git a/src/Discord.Net.Serialization/Discord.Net.Serialization.csproj b/src/Discord.Net.Serialization/Discord.Net.Serialization.csproj new file mode 100644 index 000000000..5d2cba89e --- /dev/null +++ b/src/Discord.Net.Serialization/Discord.Net.Serialization.csproj @@ -0,0 +1,18 @@ + + + + Discord.Net.Serialization + Discord.Serialization + The core components for the Discord.Net library. + net45;netstandard1.1;netstandard1.3 + true + + + + + + + + + + diff --git a/src/Discord.Net.Serialization/Extensions/BufferExtensions.cs b/src/Discord.Net.Serialization/Extensions/BufferExtensions.cs new file mode 100644 index 000000000..c0b95ba2d --- /dev/null +++ b/src/Discord.Net.Serialization/Extensions/BufferExtensions.cs @@ -0,0 +1,111 @@ +using System; +using System.Text; +using System.Text.Utf8; + +namespace Discord.Serialization +{ + public static class BufferExtensions + { + private static readonly ParsedFormat _numberFormat = new ParsedFormat('D'); + + public static bool ParseBool(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseBoolean(text, out bool result, out int ignored, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Boolean"); + } + + public static sbyte ParseInt8(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseSByte(text, out sbyte result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Int8"); + } + public static short ParseInt16(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseInt16(text, out short result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Int16"); + } + public static int ParseInt32(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseInt32(text, out int result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Int32"); + } + public static long ParseInt64(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseInt64(text, out long result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Int64"); + } + + public static byte ParseUInt8(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseByte(text, out byte result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse UInt8"); + } + public static ushort ParseUInt16(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseUInt16(text, out ushort result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse UInt16"); + } + public static uint ParseUInt32(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseUInt32(text, out uint result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse UInt32"); + } + public static ulong ParseUInt64(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseUInt64(text, out ulong result, out int ignored, _numberFormat, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse UInt64"); + } + + public static char ParseChar(this ReadOnlySpan text) + { + string str = ParseString(text); + if (str.Length == 1) + return str[0]; + throw new SerializationException("Failed to parse Char"); + } + public static string ParseString(this ReadOnlySpan text) => new Utf8String(text).ToString(); + + public static float ParseSingle(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) + return (float)result; + throw new SerializationException("Failed to parse Single"); + } + public static double ParseDouble(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) + return (double)result; + throw new SerializationException("Failed to parse Double"); + } + public static decimal ParseDecimal(this ReadOnlySpan text) + { + if (PrimitiveParser.TryParseDecimal(text, out decimal result, out int ignored, SymbolTable.InvariantUtf8)) + return result; + throw new SerializationException("Failed to parse Decimal"); + } + + public static DateTime ParseDateTime(this ReadOnlySpan text) + { + string str = ParseString(text); + if (DateTime.TryParse(str, out var result)) //TODO: Improve perf + return result; + throw new SerializationException("Failed to parse DateTime"); + } + public static DateTimeOffset ParseDateTimeOffset(this ReadOnlySpan text) + { + string str = ParseString(text); + if (DateTimeOffset.TryParse(str, out var result)) //TODO: Improve perf + return result; + throw new SerializationException("Failed to parse DateTimeOffset"); + } + } +} diff --git a/src/Discord.Net.Serialization/Extensions/JsonReaderExtensions.cs b/src/Discord.Net.Serialization/Extensions/JsonReaderExtensions.cs new file mode 100644 index 000000000..7f8a45f61 --- /dev/null +++ b/src/Discord.Net.Serialization/Extensions/JsonReaderExtensions.cs @@ -0,0 +1,36 @@ +using System; +using System.Text.Json; + +namespace Discord.Serialization +{ + public static class JsonReaderExtensions + { + public static bool ParseBool(this JsonReader reader) => reader.Value.ParseBool(); + + public static sbyte ParseInt8(this JsonReader reader) => reader.Value.ParseInt8(); + public static short ParseInt16(this JsonReader reader) => reader.Value.ParseInt16(); + public static int ParseInt32(this JsonReader reader) => reader.Value.ParseInt32(); + public static long ParseInt64(this JsonReader reader) => reader.Value.ParseInt64(); + + public static byte ParseUInt8(this JsonReader reader) => reader.Value.ParseUInt8(); + public static ushort ParseUInt16(this JsonReader reader) => reader.Value.ParseUInt16(); + public static uint ParseUInt32(this JsonReader reader) => reader.Value.ParseUInt32(); + public static ulong ParseUInt64(this JsonReader reader) => reader.Value.ParseUInt64(); + + public static char ParseChar(this JsonReader reader) => reader.Value.ParseChar(); + public static string ParseString(this JsonReader reader) => reader.Value.ParseString(); + + public static float ParseSingle(this JsonReader reader) => reader.Value.ParseSingle(); + public static double ParseDouble(this JsonReader reader) => reader.Value.ParseDouble(); + public static decimal ParseDecimal(this JsonReader reader) => reader.Value.ParseDecimal(); + + public static DateTime ParseDateTime(this JsonReader reader) => reader.Value.ParseDateTime(); + public static DateTimeOffset ParseDateTimeOffset(this JsonReader reader) => reader.Value.ParseDateTimeOffset(); + + public static void Skip(this JsonReader reader) + { + int initialDepth = reader._depth; + while (reader.Read() && reader._depth > initialDepth) { } + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/Converters/ListPropertyConverter.cs b/src/Discord.Net.Serialization/Json/Converters/Collections.cs similarity index 55% rename from src/Discord.Net.Rest/Serialization/Converters/ListPropertyConverter.cs rename to src/Discord.Net.Serialization/Json/Converters/Collections.cs index b1627bc5c..0b6fcaae1 100644 --- a/src/Discord.Net.Rest/Serialization/Converters/ListPropertyConverter.cs +++ b/src/Discord.Net.Serialization/Json/Converters/Collections.cs @@ -1,33 +1,33 @@ using System.Collections.Generic; using System.Text.Json; -namespace Discord.Serialization.Converters +namespace Discord.Serialization.Json.Converters { - internal class ListPropertyConverter : IPropertyConverter> + internal class ListPropertyConverter : IJsonPropertyConverter> { - private readonly IPropertyConverter _innerConverter; + private readonly IJsonPropertyConverter _innerConverter; - public ListPropertyConverter(IPropertyConverter innerConverter) + public ListPropertyConverter(IJsonPropertyConverter innerConverter) { _innerConverter = innerConverter; } - public List ReadJson(JsonReader reader, bool read = true) + public List Read(JsonReader reader, bool read = true) { if ((read && !reader.Read()) || reader.TokenType != JsonTokenType.StartArray) throw new SerializationException("Bad input, expected StartArray"); var list = new List(); while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) - list.Add(_innerConverter.ReadJson(reader)); + list.Add(_innerConverter.Read(reader)); return list; } - public void WriteJson(JsonWriter writer, List value) + public void Write(JsonWriter writer, List value) { writer.WriteArrayStart(); for (int i = 0; i < value.Count; i++) - _innerConverter.WriteJson(writer, value[i]); + _innerConverter.Write(writer, value[i]); writer.WriteArrayEnd(); } } diff --git a/src/Discord.Net.Serialization/Json/Converters/Nullable.cs b/src/Discord.Net.Serialization/Json/Converters/Nullable.cs new file mode 100644 index 000000000..625f4401c --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Nullable.cs @@ -0,0 +1,32 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class NullablePropertyConverter : IJsonPropertyConverter + where T : struct + { + private readonly IJsonPropertyConverter _innerConverter; + + public NullablePropertyConverter(IJsonPropertyConverter innerConverter) + { + _innerConverter = innerConverter; + } + + public T? Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType == JsonValueType.Null) + return null; + return _innerConverter.Read(reader, false); + } + + public void Write(JsonWriter writer, T? value) + { + if (value.HasValue) + _innerConverter.Write(writer, value.Value); + else + writer.WriteNull(); + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/Converters/Primitives/BooleanPropertyConverter.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.Bool.cs similarity index 63% rename from src/Discord.Net.Rest/Serialization/Converters/Primitives/BooleanPropertyConverter.cs rename to src/Discord.Net.Serialization/Json/Converters/Primitives.Bool.cs index e55acd113..d8daad23b 100644 --- a/src/Discord.Net.Rest/Serialization/Converters/Primitives/BooleanPropertyConverter.cs +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.Bool.cs @@ -1,10 +1,10 @@ using System.Text.Json; -namespace Discord.Serialization.Converters +namespace Discord.Serialization.Json.Converters { - internal class BooleanPropertyConverter : IPropertyConverter + internal class BooleanPropertyConverter : IJsonPropertyConverter { - public bool ReadJson(JsonReader reader, bool read = true) + public bool Read(JsonReader reader, bool read = true) { if (read) reader.Read(); @@ -15,7 +15,7 @@ namespace Discord.Serialization.Converters default: throw new SerializationException("Bad input, expected False or True"); } } - public void WriteJson(JsonWriter writer, bool value) + public void Write(JsonWriter writer, bool value) => writer.WriteValue(value); } } diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.DateTime.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.DateTime.cs new file mode 100644 index 000000000..3f5d9ccd7 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.DateTime.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class DateTimePropertyConverter : IJsonPropertyConverter + { + public DateTime Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseDateTime(); + } + public void Write(JsonWriter writer, DateTime value) + => writer.WriteValue(value); + } + + internal class DateTimeOffsetPropertyConverter : IJsonPropertyConverter + { + public DateTimeOffset Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseDateTimeOffset(); + } + public void Write(JsonWriter writer, DateTimeOffset value) + => writer.WriteValue(value); + } +} diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.Enum.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.Enum.cs new file mode 100644 index 000000000..da19e8684 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.Enum.cs @@ -0,0 +1,12 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class EnumPropertyConverter : IJsonPropertyConverter + { + public T Read(JsonReader reader, bool read = true) + => throw new System.NotImplementedException(); + public void Write(JsonWriter writer, T value) + => throw new System.NotImplementedException(); + } +} diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.Float.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.Float.cs new file mode 100644 index 000000000..f8824113c --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.Float.cs @@ -0,0 +1,46 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class SinglePropertyConverter : IJsonPropertyConverter + { + public float Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseSingle(); + } + public void Write(JsonWriter writer, float value) + => writer.WriteValue(value.ToString()); + } + + internal class DoublePropertyConverter : IJsonPropertyConverter + { + public double Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseDouble(); + } + public void Write(JsonWriter writer, double value) + => writer.WriteValue(value.ToString()); + } + + internal class DecimalPropertyConverter : IJsonPropertyConverter + { + public decimal Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseDecimal(); + } + public void Write(JsonWriter writer, decimal value) + => writer.WriteValue(value.ToString()); + } +} diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.Signed.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.Signed.cs new file mode 100644 index 000000000..a3ade8507 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.Signed.cs @@ -0,0 +1,60 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class Int8PropertyConverter : IJsonPropertyConverter + { + public sbyte Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseInt8(); + } + public void Write(JsonWriter writer, sbyte value) + => writer.WriteValue(value); + } + + internal class Int16PropertyConverter : IJsonPropertyConverter + { + public short Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseInt16(); + } + public void Write(JsonWriter writer, short value) + => writer.WriteValue(value); + } + + internal class Int32PropertyConverter : IJsonPropertyConverter + { + public int Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseInt32(); + } + public void Write(JsonWriter writer, int value) + => writer.WriteValue(value); + } + + internal class Int64PropertyConverter : IJsonPropertyConverter + { + public long Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseInt64(); + } + public void Write(JsonWriter writer, long value) + => writer.WriteValue(value.ToString()); + } +} diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.String.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.String.cs new file mode 100644 index 000000000..90c8604e8 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.String.cs @@ -0,0 +1,32 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class CharPropertyConverter : IJsonPropertyConverter + { + public char Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseChar(); + } + public void Write(JsonWriter writer, char value) + => writer.WriteValue(value); + } + + internal class StringPropertyConverter : IJsonPropertyConverter + { + public string Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseString(); + } + public void Write(JsonWriter writer, string value) + => writer.WriteValue(value); + } +} diff --git a/src/Discord.Net.Serialization/Json/Converters/Primitives.Unsigned.cs b/src/Discord.Net.Serialization/Json/Converters/Primitives.Unsigned.cs new file mode 100644 index 000000000..3afa66a74 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/Converters/Primitives.Unsigned.cs @@ -0,0 +1,60 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json.Converters +{ + internal class UInt8PropertyConverter : IJsonPropertyConverter + { + public byte Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseUInt8(); + } + public void Write(JsonWriter writer, byte value) + => writer.WriteValue(value); + } + + internal class UInt16PropertyConverter : IJsonPropertyConverter + { + public ushort Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseUInt16(); + } + public void Write(JsonWriter writer, ushort value) + => writer.WriteValue(value); + } + + internal class UInt32PropertyConverter : IJsonPropertyConverter + { + public uint Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.Number) + throw new SerializationException("Bad input, expected Number"); + return reader.ParseUInt32(); + } + public void Write(JsonWriter writer, uint value) + => writer.WriteValue(value); + } + + internal class UInt64PropertyConverter : IJsonPropertyConverter + { + public ulong Read(JsonReader reader, bool read = true) + { + if (read) + reader.Read(); + if (reader.ValueType != JsonValueType.String) + throw new SerializationException("Bad input, expected String"); + return reader.ParseUInt64(); + } + public void Write(JsonWriter writer, ulong value) + => writer.WriteValue(value.ToString()); + } +} diff --git a/src/Discord.Net.Serialization/Json/IJsonPropertyConverter.cs b/src/Discord.Net.Serialization/Json/IJsonPropertyConverter.cs new file mode 100644 index 000000000..f09acb1b7 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/IJsonPropertyConverter.cs @@ -0,0 +1,10 @@ +using System.Text.Json; + +namespace Discord.Serialization.Json +{ + public interface IJsonPropertyConverter + { + T Read(JsonReader reader, bool read = true); + void Write(JsonWriter writer, T value); + } +} diff --git a/src/Discord.Net.Serialization/Json/IJsonPropertyMap.cs b/src/Discord.Net.Serialization/Json/IJsonPropertyMap.cs new file mode 100644 index 000000000..eab665bde --- /dev/null +++ b/src/Discord.Net.Serialization/Json/IJsonPropertyMap.cs @@ -0,0 +1,12 @@ +using System.Text.Json; + +namespace Discord.Serialization +{ + internal interface IJsonPropertyMap + { + string Key { get; } + + void Write(TModel model, JsonWriter writer); + void Read(TModel model, JsonReader reader); + } +} diff --git a/src/Discord.Net.Serialization/Json/JsonFormat.cs b/src/Discord.Net.Serialization/Json/JsonFormat.cs new file mode 100644 index 000000000..4681041a3 --- /dev/null +++ b/src/Discord.Net.Serialization/Json/JsonFormat.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using System.Text.Formatting; +using System.Text.Json; + +namespace Discord.Serialization.Json +{ + public class JsonFormat : SerializationFormat + { + public JsonFormat() + { + AddConverter(); + + AddConverter(); + AddConverter(); + AddConverter(); + AddConverter(); + + AddConverter(); + AddConverter(); + AddConverter(); + AddConverter(); + + AddConverter(); + AddConverter(); + AddConverter(); + + AddConverter(); + AddConverter(); + + AddConverter(); + AddConverter(); + + AddGenericConverter(typeof(List<>), typeof(Converters.ListPropertyConverter<>)); + AddGenericConverter(typeof(Nullable<>), typeof(Converters.NullablePropertyConverter<>)); + + //AddEnumConverter(); + } + + public void AddConverter() + where TConverter : class, IJsonPropertyConverter + => _converters.Add(); + public void AddConverter(Func condition) + where TConverter : class, IJsonPropertyConverter + => _converters.Add(condition); + + public void AddGenericConverter(Type value, Type converter) + => _converters.AddGeneric(value, converter); + public void AddGenericConverter(Type value, Type converter, Func condition) + => _converters.AddGeneric(value, converter); + + protected override PropertyMap CreatePropertyMap(PropertyInfo propInfo) + { + var converter = (IJsonPropertyConverter)_converters.Get(propInfo); + return new JsonPropertyMap(propInfo, converter); + } + + protected internal override TModel Read(Serializer serializer, ReadOnlyBuffer data) + { + var reader = new JsonReader(data.Span, SymbolTable.InvariantUtf8); + var map = MapModel(); + var model = new TModel(); + + if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) + throw new InvalidOperationException("Bad input, expected StartObject"); + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + return model; + if (reader.TokenType != JsonTokenType.PropertyName) + throw new InvalidOperationException("Bad input, expected PropertyName"); + + string key = reader.ParseString(); + if (map.PropertiesByKey.TryGetValue(key, out var property)) + (property as IJsonPropertyMap).Read(model, reader); + else + reader.Skip(); //Unknown property, skip + + if (!reader.Read()) + throw new InvalidOperationException("Bad input, expected Value"); + } + throw new InvalidOperationException("Bad input, expected EndObject"); + } + + protected internal override void Write(Serializer serializer, ArrayFormatter stream, TModel model) + { + var writer = new JsonWriter(stream); + var map = MapModel(); + + writer.WriteObjectStart(); + for (int i = 0; i < map.Properties.Length; i++) + { + var property = map.Properties[i]; + writer.WriteStartAttribute(property.Key); + (property as IJsonPropertyMap).Write(model, writer); + } + writer.WriteObjectEnd(); + } + } +} diff --git a/src/Discord.Net.Serialization/Json/JsonPropertyMap.cs b/src/Discord.Net.Serialization/Json/JsonPropertyMap.cs new file mode 100644 index 000000000..5d745deee --- /dev/null +++ b/src/Discord.Net.Serialization/Json/JsonPropertyMap.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; +using System.Text.Json; + +namespace Discord.Serialization.Json +{ + internal class JsonPropertyMap : PropertyMap, IJsonPropertyMap + { + private readonly IJsonPropertyConverter _converter; + private readonly Func _getFunc; + private readonly Action _setFunc; + + public JsonPropertyMap(PropertyInfo propInfo, IJsonPropertyConverter converter) + : base(propInfo) + { + _converter = converter; + + _getFunc = propInfo.GetMethod.CreateDelegate(typeof(Func)) as Func; + _setFunc = propInfo.SetMethod.CreateDelegate(typeof(Action)) as Action; + } + + public void Write(TModel model, JsonWriter writer) + { + var value = _getFunc(model); + _converter.Write(writer, value); + } + public void Read(TModel model, JsonReader reader) + { + var value = _converter.Read(reader); + _setFunc(model, value); + } + } +} diff --git a/src/Discord.Net.Serialization/ModelMap.cs b/src/Discord.Net.Serialization/ModelMap.cs new file mode 100644 index 000000000..bf3d8923d --- /dev/null +++ b/src/Discord.Net.Serialization/ModelMap.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Discord.Serialization +{ + public class ModelMap + where TModel : class, new() + { + public readonly PropertyMap[] Properties; + public readonly Dictionary PropertiesByKey; + + public ModelMap(Dictionary properties) + { + PropertiesByKey = properties; + Properties = PropertiesByKey.Values.ToArray(); + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/ModelPropertyAttribute.cs b/src/Discord.Net.Serialization/ModelPropertyAttribute.cs similarity index 81% rename from src/Discord.Net.Rest/Serialization/ModelPropertyAttribute.cs rename to src/Discord.Net.Serialization/ModelPropertyAttribute.cs index e69da541a..185576e43 100644 --- a/src/Discord.Net.Rest/Serialization/ModelPropertyAttribute.cs +++ b/src/Discord.Net.Serialization/ModelPropertyAttribute.cs @@ -2,7 +2,7 @@ namespace Discord.Serialization { - internal class ModelPropertyAttribute : Attribute + public class ModelPropertyAttribute : Attribute { public string Key { get; } public bool IgnoreNull { get; set; } diff --git a/src/Discord.Net.Serialization/PropertyMap.cs b/src/Discord.Net.Serialization/PropertyMap.cs new file mode 100644 index 000000000..4102f8ecc --- /dev/null +++ b/src/Discord.Net.Serialization/PropertyMap.cs @@ -0,0 +1,18 @@ +using System.Reflection; + +namespace Discord.Serialization +{ + public abstract class PropertyMap + { + public string Key { get; } + + public PropertyMap(PropertyInfo propInfo) + { + var jsonProperty = propInfo.GetCustomAttribute(); + if (jsonProperty != null) + Key = jsonProperty.Key; + else + Key = propInfo.Name; + } + } +} diff --git a/src/Discord.Net.Rest/Serialization/SerializationException.cs b/src/Discord.Net.Serialization/SerializationException.cs similarity index 83% rename from src/Discord.Net.Rest/Serialization/SerializationException.cs rename to src/Discord.Net.Serialization/SerializationException.cs index 66297de9e..25daa09cd 100644 --- a/src/Discord.Net.Rest/Serialization/SerializationException.cs +++ b/src/Discord.Net.Serialization/SerializationException.cs @@ -2,7 +2,7 @@ namespace Discord.Serialization { - internal class SerializationException : Exception + public class SerializationException : Exception { public SerializationException() : base("Serialization failed") diff --git a/src/Discord.Net.Serialization/SerializationFormat.cs b/src/Discord.Net.Serialization/SerializationFormat.cs new file mode 100644 index 000000000..f53b73153 --- /dev/null +++ b/src/Discord.Net.Serialization/SerializationFormat.cs @@ -0,0 +1,57 @@ +using Discord.Serialization.Json; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.Formatting; + +namespace Discord.Serialization +{ + public abstract class SerializationFormat + { + private static readonly MethodInfo _getConverterMethod + = typeof(SerializationFormat).GetTypeInfo().GetDeclaredMethod(nameof(CreatePropertyMap)); + + private static readonly Lazy _json = new Lazy(() => new JsonFormat()); + public static JsonFormat Json => _json.Value; + + protected readonly ConcurrentDictionary _maps = new ConcurrentDictionary(); + protected readonly ConverterCollection _converters = new ConverterCollection(); + + protected ModelMap MapModel() + where TModel : class, new() + { + return _maps.GetOrAdd(typeof(TModel), _ => + { + var type = typeof(TModel).GetTypeInfo(); + var properties = new Dictionary(); + + var propInfos = type.DeclaredProperties.ToArray(); + for (int i = 0; i < propInfos.Length; i++) + { + var propInfo = propInfos[i]; + if (!propInfo.CanRead || !propInfo.CanWrite) + continue; + + var propMap = MapProperty(propInfo); + properties.Add(propMap.Key, propMap); + } + return new ModelMap(properties); + }) as ModelMap; + } + + private PropertyMap MapProperty(PropertyInfo propInfo) + where TModel : class, new() + => _getConverterMethod.MakeGenericMethod(typeof(TModel), propInfo.PropertyType).Invoke(this, new object[] { propInfo }) as PropertyMap; + + + protected internal abstract TModel Read(Serializer serializer, ReadOnlyBuffer data) + where TModel : class, new(); + protected internal abstract void Write(Serializer serializer, ArrayFormatter stream, TModel model) + where TModel : class, new(); + + protected abstract PropertyMap CreatePropertyMap(PropertyInfo propInfo) + where TModel : class, new(); + } +} diff --git a/src/Discord.Net.Serialization/Serializer.cs b/src/Discord.Net.Serialization/Serializer.cs new file mode 100644 index 000000000..7c08177e6 --- /dev/null +++ b/src/Discord.Net.Serialization/Serializer.cs @@ -0,0 +1,27 @@ +using System; +using System.Text.Formatting; + +namespace Discord.Serialization +{ + public class Serializer + { + private readonly static Lazy _json = new Lazy(() => new Serializer(SerializationFormat.Json)); + public static Serializer Json => _json.Value; + + public event Action Error; //TODO: Impl + + private readonly SerializationFormat _format; + + public Serializer(SerializationFormat format) + { + _format = format; + } + + public T Read(ReadOnlyBuffer data) + where T : class, new() + => _format.Read(this, data); + public void Write(ArrayFormatter data, T obj) + where T : class, new() + => _format.Write(this, data, obj); + } +} diff --git a/src/Discord.Net.Core/_corefxlab/BufferExtensions.cs b/src/Discord.Net.Serialization/_corefxlab/ExperimentalBufferExtensions.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/BufferExtensions.cs rename to src/Discord.Net.Serialization/_corefxlab/ExperimentalBufferExtensions.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/BufferReader.cs b/src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/BufferReader.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/BufferReader.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/BufferReader.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/BufferWriter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/BufferWriter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/BufferWriter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/BufferWriter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/UnsafeUtilities.cs b/src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/UnsafeUtilities.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Binary/System/Binary/UnsafeUtilities.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Binary/System/Binary/UnsafeUtilities.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/Buffer.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/Buffer.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/Buffer.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/Buffer.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferHandle.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferHandle.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferHandle.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferHandle.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferPool.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferPool.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferPool.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/BufferPool.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/IOutput.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/IOutput.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/IOutput.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/IOutput.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/IRetainable.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/IRetainable.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/IRetainable.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/IRetainable.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/OwnedBuffer.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/OwnedBuffer.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/OwnedBuffer.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/OwnedBuffer.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/Transformation.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/Transformation.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Buffers/Transformation.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Buffers/Transformation.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Internal/ManagedBufferPool.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Internal/ManagedBufferPool.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Internal/ManagedBufferPool.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Internal/ManagedBufferPool.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Internal/OwnedArray.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Internal/OwnedArray.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Internal/OwnedArray.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Internal/OwnedArray.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferDebuggerView.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferDebuggerView.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferDebuggerView.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferDebuggerView.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferPrimitivesThrowHelper.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferPrimitivesThrowHelper.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferPrimitivesThrowHelper.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/BufferPrimitivesThrowHelper.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/Contract.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/Contract.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/Contract.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/Contract.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/HashingHelper.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/HashingHelper.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/HashingHelper.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/HashingHelper.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/ReadOnlyBufferDebuggerView.cs b/src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/ReadOnlyBufferDebuggerView.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Buffers.Primitives/System/Runtime/ReadOnlyBufferDebuggerView.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Buffers.Primitives/System/Runtime/ReadOnlyBufferDebuggerView.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs b/src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs b/src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/Position.cs b/src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/Position.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/Position.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/Position.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ResizableArray.cs b/src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ResizableArray.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ResizableArray.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/ResizableArray.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/SequenceEnumerator.cs b/src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/SequenceEnumerator.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/SequenceEnumerator.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Collections.Sequences/System/Collections/Sequences/SequenceEnumerator.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/CompositeFormat.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/CompositeFormat.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/CompositeFormat.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/CompositeFormat.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/ArrayFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/ArrayFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/ArrayFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/ArrayFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/OutputFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/OutputFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/OutputFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/OutputFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StreamFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StreamFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StreamFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StreamFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StringFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StringFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StringFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/Formatters/StringFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/IOutputExtensions.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/IOutputExtensions.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/IOutputExtensions.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/IOutputExtensions.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutput.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutput.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutput.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutput.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutputExtensions.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutputExtensions.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutputExtensions.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Formatting/ITextOutputExtensions.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonConstants.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonConstants.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonConstants.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonConstants.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonEncoderState.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonEncoderState.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonEncoderState.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonEncoderState.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonParseObject.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonParseObject.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonParseObject.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonParseObject.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonParser.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonParser.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonParser.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonParser.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonReaderException.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReaderException.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonReaderException.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReaderException.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonTokenType.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonTokenType.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonTokenType.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonTokenType.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonValueType.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonValueType.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonValueType.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonValueType.cs diff --git a/src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs similarity index 100% rename from src/Discord.Net.Rest/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Precondition.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Precondition.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Precondition.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Precondition.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_casing.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_casing.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_casing.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_casing.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_encoding.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_encoding.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_encoding.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Ascii/Ascii_encoding.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf16.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf16.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf16.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf16.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf32.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf32.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf32.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf32.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf8.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf8.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf8.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/Encoders.Utf8.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/EncodingHelper.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/EncodingHelper.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/EncodingHelper.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/EncodingHelper.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/ParsingTrie.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/ParsingTrie.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/ParsingTrie.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/ParsingTrie.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Symbol.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Symbol.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Symbol.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Symbol.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf16.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf16.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf16.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf16.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf8.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf8.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf8.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.Utf8.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Encoding/SymbolTable.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/FloatFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/FloatFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/FloatFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/FloatFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/IBufferFormattable.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/IBufferFormattable.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/IBufferFormattable.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/IBufferFormattable.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/FormattingHelpers.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/FormattingHelpers.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/FormattingHelpers.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/FormattingHelpers.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf16.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf16.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf16.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf16.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf8.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf8.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf8.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/GuidFormatter.Utf8.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf16.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf16.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf16.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf16.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf8.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf8.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf8.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.Utf8.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/IntegerFormatter.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf16.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf16.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf16.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf16.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf8.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf8.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf8.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/Internal/TimeFormatter.Utf8.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Guid.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Guid.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Guid.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Guid.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Integer.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Integer.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Integer.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Integer.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Time.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Time.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Time.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter.Time.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter_float.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter_float.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter_float.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Formatting/PrimitiveFormatter_float.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/ParsedFormat.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/ParsedFormat.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/ParsedFormat.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/ParsedFormat.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantBool.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantBool.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantBool.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantBool.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSigned.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSigned.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSigned.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSigned.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSignedHex.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSignedHex.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSignedHex.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantSignedHex.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsigned.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsigned.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsigned.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsigned.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsignedHex.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsignedHex.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsignedHex.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUnsignedHex.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf16_decimal.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf16_decimal.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf16_decimal.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf16_decimal.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf8_decimal.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf8_decimal.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf8_decimal.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/InvariantUtf8_decimal.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Boolean.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Boolean.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Boolean.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Boolean.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Decimal.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Decimal.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Decimal.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/PrimitiveParser_Decimal.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/Signed.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/Signed.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/Signed.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/Signed.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/Unsigned.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/Unsigned.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Primitives/System/Text/Parsing/Unsigned.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Primitives/System/Text/Parsing/Unsigned.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerable.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerable.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerable.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerable.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerator.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerator.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerator.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf16LittleEndianCodePointEnumerator.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8Helper.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8Helper.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8Helper.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8Helper.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerable.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerable.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerable.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerable.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerator.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerator.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerator.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointEnumerator.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointReverseEnumerator.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointReverseEnumerator.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointReverseEnumerator.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.CodePointReverseEnumerator.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.Enumerator.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.Enumerator.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.Enumerator.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.Enumerator.cs diff --git a/src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.cs similarity index 100% rename from src/Discord.Net.Core/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.cs rename to src/Discord.Net.Serialization/_corefxlab/System.Text.Utf8String/System/Text/Utf8String.cs diff --git a/src/Discord.Net.WebSocket/Audio/AudioClient.cs b/src/Discord.Net.WebSocket/Audio/AudioClient.cs index 9b2d9c7b6..75d08424c 100644 --- a/src/Discord.Net.WebSocket/Audio/AudioClient.cs +++ b/src/Discord.Net.WebSocket/Audio/AudioClient.cs @@ -30,7 +30,7 @@ namespace Discord.Audio } private readonly Logger _audioLogger; - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; private readonly ConnectionManager _connection; private readonly SemaphoreSlim _stateLock; private readonly ConcurrentQueue _heartbeatTimes; @@ -66,10 +66,10 @@ namespace Discord.Audio ChannelId = channelId; _audioLogger = Discord.LogManager.CreateLogger($"Audio #{clientId}"); - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _audioLogger.WarningAsync("Serializer Error", ex); + _audioLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; ApiClient = new DiscordVoiceApiClient(guild.Id, Discord.WebSocketProvider, Discord.UdpSocketProvider, _serializer); @@ -236,7 +236,7 @@ namespace Discord.Audio case VoiceOpCode.Ready: { await _audioLogger.DebugAsync("Received Ready").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); _ssrc = data.SSRC; @@ -252,7 +252,7 @@ namespace Discord.Audio case VoiceOpCode.SessionDescription: { await _audioLogger.DebugAsync("Received SessionDescription").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.Mode != DiscordVoiceApiClient.Mode) throw new InvalidOperationException($"Discord selected an unexpected mode: {data.Mode}"); @@ -288,7 +288,7 @@ namespace Discord.Audio { await _audioLogger.DebugAsync("Received Speaking").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); _ssrcMap[data.Ssrc] = data.UserId; //TODO: Memory Leak: SSRCs are never cleaned up await _speakingUpdatedEvent.InvokeAsync(data.UserId, data.Speaking); diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index 9d199ed69..7a60aea39 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -14,7 +14,7 @@ namespace Discord.WebSocket { private readonly DiscordSocketConfig _baseConfig; private readonly SemaphoreSlim _connectionGroupLock; - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; private int[] _shardIds; private Dictionary _shardIdsToIndex; @@ -54,10 +54,10 @@ namespace Discord.WebSocket _baseConfig = config; _connectionGroupLock = new SemaphoreSlim(1, 1); - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _restLogger.WarningAsync("Serializer Error", ex); + _restLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; SetApiClient(new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordConfig.UserAgent, _serializer)); diff --git a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs index 8d6c8aca7..4e8b2fe28 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs @@ -36,7 +36,7 @@ namespace Discord.API public ConnectionState ConnectionState { get; private set; } - public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent, ScopedSerializer serializer, + public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent, Serializer serializer, string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) : base(restClientProvider, userAgent, serializer, defaultRetryMode) { @@ -60,14 +60,14 @@ namespace Discord.API _decompressionStream.SetLength(_decompressionStream.Position); _decompressionStream.Position = 0; - var msg = _serializer.ReadJson(_decompressionStream.ToReadOnlyBuffer()); + var msg = _serializer.Read(_decompressionStream.ToReadOnlyBuffer()); if (msg != null) await _receivedGatewayEvent.InvokeAsync((GatewayOpCode)msg.Operation, msg.Sequence, msg.Type, msg.Payload).ConfigureAwait(false); } } else { - var msg = _serializer.ReadJson(data); + var msg = _serializer.Read(data); if (msg != null) await _receivedGatewayEvent.InvokeAsync((GatewayOpCode)msg.Operation, msg.Sequence, msg.Type, msg.Payload).ConfigureAwait(false); } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 6a4bc7d6f..2816c8041 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -22,7 +22,7 @@ namespace Discord.WebSocket { private readonly ConcurrentQueue _largeGuilds; private readonly SemaphoreSlim _connectionGroupLock, _stateLock; - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; private readonly DiscordSocketClient _parentClient; private readonly ConcurrentQueue _heartbeatTimes; private readonly ConnectionManager _connection; @@ -87,10 +87,10 @@ namespace Discord.WebSocket _stateLock = new SemaphoreSlim(1, 1); _gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : $"Shard #{ShardId}"); - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _restLogger.WarningAsync("Serializer Error", ex); + _restLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; SetApiClient(new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordConfig.UserAgent, _serializer, config.GatewayHost, config.DefaultRetryMode)); @@ -395,7 +395,7 @@ namespace Discord.WebSocket case GatewayOpCode.Hello: { await _gatewayLogger.DebugAsync("Received Hello").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); _heartbeatTask = RunHeartbeatAsync(data.HeartbeatInterval, _connection.CancelToken); } @@ -451,7 +451,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var state = new ClientState(data.Guilds.Length, data.PrivateChannels.Length); var currentUser = SocketSelfUser.Create(this, state, data.User); @@ -521,7 +521,7 @@ namespace Discord.WebSocket //Guilds case "GUILD_CREATE": { - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.Unavailable == false) { @@ -573,7 +573,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.Id); if (guild != null) { @@ -592,7 +592,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_EMOJIS_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -610,7 +610,7 @@ namespace Discord.WebSocket case "GUILD_SYNC": { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_SYNC)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.Id); if (guild != null) { @@ -631,7 +631,7 @@ namespace Discord.WebSocket break; case "GUILD_DELETE": { - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.Unavailable == true) { type = "GUILD_UNAVAILABLE"; @@ -673,7 +673,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); SocketChannel channel = null; if (data.GuildId.IsSpecified) { @@ -705,7 +705,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var channel = State.GetChannel(data.Id); if (channel != null) { @@ -733,7 +733,7 @@ namespace Discord.WebSocket await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_DELETE)").ConfigureAwait(false); SocketChannel channel = null; - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.GuildId.IsSpecified) { var guild = State.GetGuild(data.GuildId.Value); @@ -771,7 +771,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_MEMBER_ADD)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -797,7 +797,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_MEMBER_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -835,7 +835,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_MEMBER_REMOVE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -870,7 +870,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_MEMBERS_CHUNK)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -894,7 +894,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_RECIPIENT_ADD)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is SocketGroupChannel channel) { var user = channel.GetOrAddUser(data.User); @@ -911,7 +911,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_RECIPIENT_REMOVE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is SocketGroupChannel channel) { var user = channel.RemoveUser(data.User.Id); @@ -936,7 +936,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_ROLE_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -960,7 +960,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_ROLE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -995,7 +995,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_ROLE_DELETE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -1029,7 +1029,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_BAN_ADD)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -1055,7 +1055,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_BAN_REMOVE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { @@ -1083,7 +1083,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var guild = (channel as SocketGuildChannel)?.Guild; @@ -1130,7 +1130,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var guild = (channel as SocketGuildChannel)?.Guild; @@ -1177,7 +1177,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var guild = (channel as SocketGuildChannel)?.Guild; @@ -1204,7 +1204,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_ADD)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; @@ -1228,7 +1228,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_REMOVE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; @@ -1252,7 +1252,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_REMOVE_ALL)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; @@ -1274,7 +1274,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE_BULK)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var guild = (channel as SocketGuildChannel)?.Guild; @@ -1305,7 +1305,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (PRESENCE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.GuildId.IsSpecified) { @@ -1364,7 +1364,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (TYPING_START)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel) { var guild = (channel as SocketGuildChannel)?.Guild; @@ -1386,7 +1386,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (USER_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); if (data.Id == CurrentUser.Id) { var before = CurrentUser.Clone(); @@ -1406,7 +1406,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); SocketUser user; SocketVoiceState before, after; if (data.GuildId != null) @@ -1478,7 +1478,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_SERVER_UPDATE)").ConfigureAwait(false); - var data = _serializer.ReadJson(payload); + var data = _serializer.Read(payload); var guild = State.GetGuild(data.GuildId); if (guild != null) { diff --git a/src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs b/src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs index b465159a1..35989f81e 100644 --- a/src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs +++ b/src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs @@ -38,7 +38,7 @@ namespace Discord.Audio public event Func Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } } private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>(); - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; private readonly SemaphoreSlim _connectionLock; private readonly MemoryStream _decompressionStream; protected readonly ConcurrentQueue _formatters; @@ -54,7 +54,7 @@ namespace Discord.Audio public ushort UdpPort => _udp.Port; - internal DiscordVoiceApiClient(ulong guildId, WebSocketProvider webSocketProvider, UdpSocketProvider udpSocketProvider, ScopedSerializer serializer) + internal DiscordVoiceApiClient(ulong guildId, WebSocketProvider webSocketProvider, UdpSocketProvider udpSocketProvider, Serializer serializer) { GuildId = guildId; _connectionLock = new SemaphoreSlim(1, 1); @@ -79,14 +79,14 @@ namespace Discord.Audio _decompressionStream.SetLength(_decompressionStream.Position); _decompressionStream.Position = 0; - var msg = _serializer.ReadJson(_decompressionStream.ToReadOnlyBuffer()); + var msg = _serializer.Read(_decompressionStream.ToReadOnlyBuffer()); if (msg != null) await _receivedEvent.InvokeAsync((VoiceOpCode)msg.Operation, msg.Payload).ConfigureAwait(false); } } else { - var msg = _serializer.ReadJson(data); + var msg = _serializer.Read(data); if (msg != null) await _receivedEvent.InvokeAsync((VoiceOpCode)msg.Operation, msg.Payload).ConfigureAwait(false); } @@ -265,13 +265,13 @@ namespace Discord.Audio private static double ToMilliseconds(Stopwatch stopwatch) => Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); protected ReadOnlyBuffer SerializeJson(ArrayFormatter data, object value) { - _serializer.WriteJson(data, value); + _serializer.Write(data, value); return new ReadOnlyBuffer(data.Formatted.Array, 0, data.Formatted.Count); } protected T DeserializeJson(ReadOnlyBuffer data) where T : class, new() { - return _serializer.ReadJson(data); + return _serializer.Read(data); } } } diff --git a/src/Discord.Net.Webhook/DiscordWebhookClient.cs b/src/Discord.Net.Webhook/DiscordWebhookClient.cs index 183711a9a..d72d4b96f 100644 --- a/src/Discord.Net.Webhook/DiscordWebhookClient.cs +++ b/src/Discord.Net.Webhook/DiscordWebhookClient.cs @@ -16,7 +16,7 @@ namespace Discord.Webhook internal readonly Logger _restLogger; private readonly ulong _webhookId; - private readonly ScopedSerializer _serializer; + private readonly Serializer _serializer; internal API.DiscordRestApiClient ApiClient { get; } internal LogManager LogManager { get; } @@ -29,10 +29,10 @@ namespace Discord.Webhook { _webhookId = webhookId; - _serializer = Serializer.CreateScope(); - _serializer.Error += async ex => + _serializer = new Serializer(SerializationFormat.Json); + _serializer.Error += ex => { - await _restLogger.WarningAsync("Serializer Error", ex); + _restLogger.WarningAsync("Serializer Error", ex).GetAwaiter().GetResult(); }; ApiClient = new API.DiscordRestApiClient(config.RestClientProvider, DiscordRestConfig.UserAgent, _serializer);