| @@ -1,6 +1,6 @@ | |||||
| { | { | ||||
| "projects": [ "src" ], | "projects": [ "src" ], | ||||
| "sdk": { | |||||
| "version": "1.0.0-rc1-update1" | |||||
| } | |||||
| "sdk": { | |||||
| "version": "1.0.0-preview1-002702" | |||||
| } | |||||
| } | } | ||||
| @@ -4,12 +4,12 @@ | |||||
| <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | ||||
| <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <PropertyGroup Label="Globals"> | <PropertyGroup Label="Globals"> | ||||
| <ProjectGuid>dff7afe3-ca77-4109-bade-b4b49a4f6648</ProjectGuid> | <ProjectGuid>dff7afe3-ca77-4109-bade-b4b49a4f6648</ProjectGuid> | ||||
| <RootNamespace>Discord.Audio</RootNamespace> | <RootNamespace>Discord.Audio</RootNamespace> | ||||
| <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||||
| <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||||
| <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <SchemaVersion>2.0</SchemaVersion> | <SchemaVersion>2.0</SchemaVersion> | ||||
| @@ -17,5 +17,5 @@ | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||||
| <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| </Project> | </Project> | ||||
| @@ -120,7 +120,7 @@ namespace Discord.Net.WebSockets | |||||
| SendIdentify(_userId.Value, _sessionId); | SendIdentify(_userId.Value, _sessionId); | ||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| tasks.Add(WatcherAsync()); | tasks.Add(WatcherAsync()); | ||||
| #endif | #endif | ||||
| tasks.AddRange(_engine.GetTasks(CancelToken)); | tasks.AddRange(_engine.GetTasks(CancelToken)); | ||||
| @@ -178,7 +178,7 @@ namespace Discord.Net.WebSockets | |||||
| await Task.Delay(1).ConfigureAwait(false); | await Task.Delay(1).ConfigureAwait(false); | ||||
| if (_udp.Available > 0) | if (_udp.Available > 0) | ||||
| { | { | ||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| packet = _udp.Receive(ref endpoint); | packet = _udp.Receive(ref endpoint); | ||||
| #else | #else | ||||
| //TODO: Is this really the only way to end a Receive call in DOTNET5_4? | //TODO: Is this really the only way to end a Receive call in DOTNET5_4? | ||||
| @@ -346,7 +346,7 @@ namespace Discord.Net.WebSockets | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| _udp.Send(voicePacket, rtpPacketLength); | |||||
| await _udp.SendAsync(voicePacket, rtpPacketLength, _endpoint).ConfigureAwait(false); | |||||
| } | } | ||||
| catch (SocketException ex) | catch (SocketException ex) | ||||
| { | { | ||||
| @@ -371,7 +371,7 @@ namespace Discord.Net.WebSockets | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| await _udp.SendAsync(pingPacket, pingPacket.Length).ConfigureAwait(false); | |||||
| await _udp.SendAsync(pingPacket, pingPacket.Length, _endpoint).ConfigureAwait(false); | |||||
| nextPingTicks = currentTicks + 5 * ticksPerSeconds; | nextPingTicks = currentTicks + 5 * ticksPerSeconds; | ||||
| } | } | ||||
| } | } | ||||
| @@ -391,7 +391,7 @@ namespace Discord.Net.WebSockets | |||||
| catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
| catch (InvalidOperationException) { } //Includes ObjectDisposedException | catch (InvalidOperationException) { } //Includes ObjectDisposedException | ||||
| } | } | ||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | ||||
| private async Task WatcherAsync() | private async Task WatcherAsync() | ||||
| { | { | ||||
| @@ -437,7 +437,6 @@ namespace Discord.Net.WebSockets | |||||
| _encryptionMode = UnencryptedMode; | _encryptionMode = UnencryptedMode; | ||||
| _isEncrypted = false; | _isEncrypted = false; | ||||
| } | } | ||||
| _udp.Connect(_endpoint); | |||||
| _sequence = 0;// (ushort)_rand.Next(0, ushort.MaxValue); | _sequence = 0;// (ushort)_rand.Next(0, ushort.MaxValue); | ||||
| //No thread issue here because SendAsync doesn't start until _isReady is true | //No thread issue here because SendAsync doesn't start until _isReady is true | ||||
| @@ -446,7 +445,7 @@ namespace Discord.Net.WebSockets | |||||
| packet[1] = (byte)(_ssrc >> 16); | packet[1] = (byte)(_ssrc >> 16); | ||||
| packet[2] = (byte)(_ssrc >> 8); | packet[2] = (byte)(_ssrc >> 8); | ||||
| packet[3] = (byte)(_ssrc >> 0); | packet[3] = (byte)(_ssrc >> 0); | ||||
| await _udp.SendAsync(packet, 70).ConfigureAwait(false); | |||||
| await _udp.SendAsync(packet, 70, _endpoint).ConfigureAwait(false); | |||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -2,26 +2,36 @@ | |||||
| "version": "0.9.1", | "version": "0.9.1", | ||||
| "description": "A Discord.Net extension adding voice support.", | "description": "A Discord.Net extension adding voice support.", | ||||
| "authors": [ "RogueException" ], | "authors": [ "RogueException" ], | ||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| "packOptions": { | |||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| }, | |||||
| "contentFiles": [ "libsodium.dll", "opus.dll" ] | |||||
| }, | }, | ||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "contentFiles": [ "libsodium.dll", "opus.dll" ], | |||||
| "compilationOptions": { | |||||
| "buildOptions": { | |||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "preserveCompilationContext": true, | |||||
| "allowUnsafe": true, | "allowUnsafe": true, | ||||
| "warningsAsErrors": true | "warningsAsErrors": true | ||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "NETStandard.Library": "1.5.0-rc2-24027", | |||||
| "Discord.Net": "0.9.1" | "Discord.Net": "0.9.1" | ||||
| }, | }, | ||||
| "frameworks": { | "frameworks": { | ||||
| "net45": { }, | |||||
| "dotnet5.4": { } | |||||
| "netstandard1.3": { | |||||
| "imports": [ | |||||
| "dotnet5.4", | |||||
| "dnxcore50", | |||||
| "portable-net45+win8" | |||||
| ] | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -4,12 +4,12 @@ | |||||
| <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | ||||
| <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <PropertyGroup Label="Globals"> | <PropertyGroup Label="Globals"> | ||||
| <ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid> | <ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid> | ||||
| <RootNamespace>Discord.Commands</RootNamespace> | <RootNamespace>Discord.Commands</RootNamespace> | ||||
| <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||||
| <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||||
| <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <SchemaVersion>2.0</SchemaVersion> | <SchemaVersion>2.0</SchemaVersion> | ||||
| @@ -17,5 +17,5 @@ | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||||
| <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| </Project> | </Project> | ||||
| @@ -2,24 +2,34 @@ | |||||
| "version": "0.9.1", | "version": "0.9.1", | ||||
| "description": "A Discord.Net extension adding basic command support.", | "description": "A Discord.Net extension adding basic command support.", | ||||
| "authors": [ "RogueException" ], | "authors": [ "RogueException" ], | ||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| "packOptions": { | |||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| } | |||||
| }, | }, | ||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "compilationOptions": { | |||||
| "buildOptions": { | |||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "preserveCompilationContext": true, | |||||
| "warningsAsErrors": true | "warningsAsErrors": true | ||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "NETStandard.Library": "1.5.0-rc2-24027", | |||||
| "Discord.Net": "0.9.1" | "Discord.Net": "0.9.1" | ||||
| }, | }, | ||||
| "frameworks": { | "frameworks": { | ||||
| "net45": { }, | |||||
| "dotnet5.4": { } | |||||
| "netstandard1.3": { | |||||
| "imports": [ | |||||
| "dotnet5.4", | |||||
| "dnxcore50", | |||||
| "portable-net45+win8" | |||||
| ] | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -4,12 +4,12 @@ | |||||
| <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | ||||
| <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <PropertyGroup Label="Globals"> | <PropertyGroup Label="Globals"> | ||||
| <ProjectGuid>01584e8a-78da-486f-9ef9-a894e435841b</ProjectGuid> | <ProjectGuid>01584e8a-78da-486f-9ef9-a894e435841b</ProjectGuid> | ||||
| <RootNamespace>Discord.Modules</RootNamespace> | <RootNamespace>Discord.Modules</RootNamespace> | ||||
| <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||||
| <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||||
| <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <SchemaVersion>2.0</SchemaVersion> | <SchemaVersion>2.0</SchemaVersion> | ||||
| @@ -17,5 +17,5 @@ | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||||
| <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| </Project> | </Project> | ||||
| @@ -2,25 +2,35 @@ | |||||
| "version": "0.9.1", | "version": "0.9.1", | ||||
| "description": "A Discord.Net extension adding basic plugin support.", | "description": "A Discord.Net extension adding basic plugin support.", | ||||
| "authors": [ "RogueException" ], | "authors": [ "RogueException" ], | ||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| "packOptions": { | |||||
| "tags": [ "discord", "discordapp" ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| } | |||||
| }, | }, | ||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "compilationOptions": { | |||||
| "buildOptions": { | |||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "preserveCompilationContext": true, | |||||
| "warningsAsErrors": true | "warningsAsErrors": true | ||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "NETStandard.Library": "1.5.0-rc2-24027", | |||||
| "Discord.Net": "0.9.1", | "Discord.Net": "0.9.1", | ||||
| "Discord.Net.Commands": "0.9.1" | "Discord.Net.Commands": "0.9.1" | ||||
| }, | }, | ||||
| "frameworks": { | "frameworks": { | ||||
| "net45": { }, | |||||
| "dotnet5.4": { } | |||||
| "netstandard1.3": { | |||||
| "imports": [ | |||||
| "dotnet5.4", | |||||
| "dnxcore50", | |||||
| "portable-net45+win8" | |||||
| ] | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -550,9 +550,6 @@ | |||||
| <Compile Include="..\Discord.Net\Net\Rest\CompletedRequestEventArgs.cs"> | <Compile Include="..\Discord.Net\Net\Rest\CompletedRequestEventArgs.cs"> | ||||
| <Link>Net\Rest\CompletedRequestEventArgs.cs</Link> | <Link>Net\Rest\CompletedRequestEventArgs.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net\Net\Rest\ETFRestClient.cs"> | |||||
| <Link>Net\Rest\ETFRestClient.cs</Link> | |||||
| </Compile> | |||||
| <Compile Include="..\Discord.Net\Net\Rest\IRestEngine.cs"> | <Compile Include="..\Discord.Net\Net\Rest\IRestEngine.cs"> | ||||
| <Link>Net\Rest\IRestEngine.cs</Link> | <Link>Net\Rest\IRestEngine.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| @@ -4,12 +4,12 @@ | |||||
| <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | ||||
| <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <PropertyGroup Label="Globals"> | <PropertyGroup Label="Globals"> | ||||
| <ProjectGuid>acfb060b-ec8a-4926-b293-04c01e17ee23</ProjectGuid> | <ProjectGuid>acfb060b-ec8a-4926-b293-04c01e17ee23</ProjectGuid> | ||||
| <RootNamespace>Discord</RootNamespace> | <RootNamespace>Discord</RootNamespace> | ||||
| <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||||
| <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||||
| <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <SchemaVersion>2.0</SchemaVersion> | <SchemaVersion>2.0</SchemaVersion> | ||||
| @@ -17,5 +17,5 @@ | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||||
| <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
| </Project> | </Project> | ||||
| @@ -243,12 +243,15 @@ namespace Discord | |||||
| } | } | ||||
| ClientAPI.Token = token; | ClientAPI.Token = token; | ||||
| var request = new LoginRequest() { Email = email, Password = password }; | |||||
| var response = await ClientAPI.Send(request).ConfigureAwait(false); | |||||
| token = response.Token; | |||||
| if (Config.CacheDir != null && token != oldToken && tokenPath != null) | |||||
| SaveToken(tokenPath, cacheKey, token); | |||||
| ClientAPI.Token = token; | |||||
| if (email != null && password != null) | |||||
| { | |||||
| var request = new LoginRequest() { Email = email, Password = password }; | |||||
| var response = await ClientAPI.Send(request).ConfigureAwait(false); | |||||
| token = response.Token; | |||||
| if (Config.CacheDir != null && token != oldToken && tokenPath != null) | |||||
| SaveToken(tokenPath, cacheKey, token); | |||||
| ClientAPI.Token = token; | |||||
| } | |||||
| //Cache other stuff | //Cache other stuff | ||||
| var regionsResponse = (await ClientAPI.Send(new GetVoiceRegionsRequest()).ConfigureAwait(false)); | var regionsResponse = (await ClientAPI.Send(new GetVoiceRegionsRequest()).ConfigureAwait(false)); | ||||
| @@ -1,491 +1,491 @@ | |||||
| using Newtonsoft.Json; | |||||
| using System; | |||||
| using System.Collections.Concurrent; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Reflection; | |||||
| using System.Reflection.Emit; | |||||
| using System.Text; | |||||
| //using Newtonsoft.Json; | |||||
| //using System; | |||||
| //using System.Collections.Concurrent; | |||||
| //using System.Collections.Generic; | |||||
| //using System.IO; | |||||
| //using System.Linq; | |||||
| //using System.Reflection; | |||||
| //using System.Reflection.Emit; | |||||
| //using System.Text; | |||||
| namespace Discord.ETF | |||||
| { | |||||
| public class ETFReader : IDisposable | |||||
| { | |||||
| private static readonly ConcurrentDictionary<Type, Delegate> _deserializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| private static readonly Dictionary<Type, MethodInfo> _readMethods = GetPrimitiveReadMethods(); | |||||
| //namespace Discord.ETF | |||||
| //{ | |||||
| // public class ETFReader : IDisposable | |||||
| // { | |||||
| // private static readonly ConcurrentDictionary<Type, Delegate> _deserializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| // private static readonly Dictionary<Type, MethodInfo> _readMethods = GetPrimitiveReadMethods(); | |||||
| private readonly Stream _stream; | |||||
| private readonly byte[] _buffer; | |||||
| private readonly bool _leaveOpen; | |||||
| private readonly Encoding _encoding; | |||||
| // private readonly Stream _stream; | |||||
| // private readonly byte[] _buffer; | |||||
| // private readonly bool _leaveOpen; | |||||
| // private readonly Encoding _encoding; | |||||
| public ETFReader(Stream stream, bool leaveOpen = false) | |||||
| { | |||||
| if (stream == null) throw new ArgumentNullException(nameof(stream)); | |||||
| // public ETFReader(Stream stream, bool leaveOpen = false) | |||||
| // { | |||||
| // if (stream == null) throw new ArgumentNullException(nameof(stream)); | |||||
| _stream = stream; | |||||
| _leaveOpen = leaveOpen; | |||||
| _buffer = new byte[11]; | |||||
| _encoding = Encoding.UTF8; | |||||
| } | |||||
| // _stream = stream; | |||||
| // _leaveOpen = leaveOpen; | |||||
| // _buffer = new byte[11]; | |||||
| // _encoding = Encoding.UTF8; | |||||
| // } | |||||
| public bool ReadBool() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT) | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| switch (_buffer[0]) //Length | |||||
| { | |||||
| case 4: | |||||
| ReadTrue(); | |||||
| return true; | |||||
| case 5: | |||||
| ReadFalse(); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| throw new InvalidDataException(); | |||||
| } | |||||
| private void ReadTrue() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 4); | |||||
| if (_buffer[0] != 't' || _buffer[1] != 'r' || _buffer[2] != 'u' || _buffer[3] != 'e') | |||||
| throw new InvalidDataException(); | |||||
| } | |||||
| private void ReadFalse() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 5); | |||||
| if (_buffer[0] != 'f' || _buffer[1] != 'a' || _buffer[2] != 'l' || _buffer[3] != 's' || _buffer[4] != 'e') | |||||
| throw new InvalidDataException(); | |||||
| } | |||||
| // public bool ReadBool() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT) | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // switch (_buffer[0]) //Length | |||||
| // { | |||||
| // case 4: | |||||
| // ReadTrue(); | |||||
| // return true; | |||||
| // case 5: | |||||
| // ReadFalse(); | |||||
| // return false; | |||||
| // } | |||||
| // } | |||||
| // throw new InvalidDataException(); | |||||
| // } | |||||
| // private void ReadTrue() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 4); | |||||
| // if (_buffer[0] != 't' || _buffer[1] != 'r' || _buffer[2] != 'u' || _buffer[3] != 'e') | |||||
| // throw new InvalidDataException(); | |||||
| // } | |||||
| // private void ReadFalse() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 5); | |||||
| // if (_buffer[0] != 'f' || _buffer[1] != 'a' || _buffer[2] != 'l' || _buffer[3] != 's' || _buffer[4] != 'e') | |||||
| // throw new InvalidDataException(); | |||||
| // } | |||||
| public int ReadSByte() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (sbyte)ReadLongInternal(type); | |||||
| } | |||||
| public uint ReadByte() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (byte)ReadLongInternal(type); | |||||
| } | |||||
| public int ReadShort() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (short)ReadLongInternal(type); | |||||
| } | |||||
| public uint ReadUShort() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (ushort)ReadLongInternal(type); | |||||
| } | |||||
| public int ReadInt() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (int)ReadLongInternal(type); | |||||
| } | |||||
| public uint ReadUInt() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (uint)ReadLongInternal(type); | |||||
| } | |||||
| public long ReadLong() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return ReadLongInternal(type); | |||||
| } | |||||
| public ulong ReadULong() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (ulong)ReadLongInternal(type); | |||||
| } | |||||
| public long ReadLongInternal(ETFType type) | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case ETFType.SMALL_INTEGER_EXT: | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| return _buffer[0]; | |||||
| case ETFType.INTEGER_EXT: | |||||
| _stream.Read(_buffer, 0, 4); | |||||
| return (_buffer[0] << 24) | (_buffer[1] << 16) | (_buffer[2] << 8) | (_buffer[3]); | |||||
| case ETFType.SMALL_BIG_EXT: | |||||
| _stream.Read(_buffer, 0, 2); | |||||
| bool isPositive = _buffer[0] == 0; | |||||
| byte count = _buffer[1]; | |||||
| // public int ReadSByte() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (sbyte)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint ReadByte() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (byte)ReadLongInternal(type); | |||||
| // } | |||||
| // public int ReadShort() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (short)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint ReadUShort() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (ushort)ReadLongInternal(type); | |||||
| // } | |||||
| // public int ReadInt() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (int)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint ReadUInt() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (uint)ReadLongInternal(type); | |||||
| // } | |||||
| // public long ReadLong() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return ReadLongInternal(type); | |||||
| // } | |||||
| // public ulong ReadULong() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (ulong)ReadLongInternal(type); | |||||
| // } | |||||
| // public long ReadLongInternal(ETFType type) | |||||
| // { | |||||
| // switch (type) | |||||
| // { | |||||
| // case ETFType.SMALL_INTEGER_EXT: | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // return _buffer[0]; | |||||
| // case ETFType.INTEGER_EXT: | |||||
| // _stream.Read(_buffer, 0, 4); | |||||
| // return (_buffer[0] << 24) | (_buffer[1] << 16) | (_buffer[2] << 8) | (_buffer[3]); | |||||
| // case ETFType.SMALL_BIG_EXT: | |||||
| // _stream.Read(_buffer, 0, 2); | |||||
| // bool isPositive = _buffer[0] == 0; | |||||
| // byte count = _buffer[1]; | |||||
| int shiftValue = (count - 1) * 8; | |||||
| ulong value = 0; | |||||
| _stream.Read(_buffer, 0, count); | |||||
| for (int i = 0; i < count; i++, shiftValue -= 8) | |||||
| value = value + _buffer[i] << shiftValue; | |||||
| if (!isPositive) | |||||
| return -(long)value; | |||||
| else | |||||
| return (long)value; | |||||
| } | |||||
| throw new InvalidDataException(); | |||||
| } | |||||
| // int shiftValue = (count - 1) * 8; | |||||
| // ulong value = 0; | |||||
| // _stream.Read(_buffer, 0, count); | |||||
| // for (int i = 0; i < count; i++, shiftValue -= 8) | |||||
| // value = value + _buffer[i] << shiftValue; | |||||
| // if (!isPositive) | |||||
| // return -(long)value; | |||||
| // else | |||||
| // return (long)value; | |||||
| // } | |||||
| // throw new InvalidDataException(); | |||||
| // } | |||||
| public float ReadSingle() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return (float)ReadDoubleInternal(type); | |||||
| } | |||||
| public double ReadDouble() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| return ReadDoubleInternal(type); | |||||
| } | |||||
| public double ReadDoubleInternal(ETFType type) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| // public float ReadSingle() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return (float)ReadDoubleInternal(type); | |||||
| // } | |||||
| // public double ReadDouble() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // return ReadDoubleInternal(type); | |||||
| // } | |||||
| // public double ReadDoubleInternal(ETFType type) | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // } | |||||
| public bool? ReadNullableBool() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT) | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| switch (_buffer[0]) //Length | |||||
| { | |||||
| case 3: | |||||
| if (ReadNil()) | |||||
| return null; | |||||
| break; | |||||
| case 4: | |||||
| ReadTrue(); | |||||
| return true; | |||||
| case 5: | |||||
| ReadFalse(); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| throw new InvalidDataException(); | |||||
| } | |||||
| public int? ReadNullableSByte() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (sbyte)ReadLongInternal(type); | |||||
| } | |||||
| public uint? ReadNullableByte() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (byte)ReadLongInternal(type); | |||||
| } | |||||
| public int? ReadNullableShort() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (short)ReadLongInternal(type); | |||||
| } | |||||
| public uint? ReadNullableUShort() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (ushort)ReadLongInternal(type); | |||||
| } | |||||
| public int? ReadNullableInt() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (int)ReadLongInternal(type); | |||||
| } | |||||
| public uint? ReadNullableUInt() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (uint)ReadLongInternal(type); | |||||
| } | |||||
| public long? ReadNullableLong() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return ReadLongInternal(type); | |||||
| } | |||||
| public ulong? ReadNullableULong() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (ulong)ReadLongInternal(type); | |||||
| } | |||||
| public float? ReadNullableSingle() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return (float)ReadDoubleInternal(type); | |||||
| } | |||||
| public double? ReadNullableDouble() | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| ETFType type = (ETFType)_buffer[0]; | |||||
| if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| return ReadDoubleInternal(type); | |||||
| } | |||||
| // public bool? ReadNullableBool() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT) | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // switch (_buffer[0]) //Length | |||||
| // { | |||||
| // case 3: | |||||
| // if (ReadNil()) | |||||
| // return null; | |||||
| // break; | |||||
| // case 4: | |||||
| // ReadTrue(); | |||||
| // return true; | |||||
| // case 5: | |||||
| // ReadFalse(); | |||||
| // return false; | |||||
| // } | |||||
| // } | |||||
| // throw new InvalidDataException(); | |||||
| // } | |||||
| // public int? ReadNullableSByte() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (sbyte)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint? ReadNullableByte() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (byte)ReadLongInternal(type); | |||||
| // } | |||||
| // public int? ReadNullableShort() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (short)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint? ReadNullableUShort() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (ushort)ReadLongInternal(type); | |||||
| // } | |||||
| // public int? ReadNullableInt() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (int)ReadLongInternal(type); | |||||
| // } | |||||
| // public uint? ReadNullableUInt() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (uint)ReadLongInternal(type); | |||||
| // } | |||||
| // public long? ReadNullableLong() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return ReadLongInternal(type); | |||||
| // } | |||||
| // public ulong? ReadNullableULong() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (ulong)ReadLongInternal(type); | |||||
| // } | |||||
| // public float? ReadNullableSingle() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return (float)ReadDoubleInternal(type); | |||||
| // } | |||||
| // public double? ReadNullableDouble() | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // ETFType type = (ETFType)_buffer[0]; | |||||
| // if (type == ETFType.SMALL_ATOM_EXT && ReadNil()) return null; | |||||
| // return ReadDoubleInternal(type); | |||||
| // } | |||||
| public string ReadString() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public byte[] ReadByteArray() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| // public string ReadString() | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // } | |||||
| // public byte[] ReadByteArray() | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // } | |||||
| public T Read<T>() | |||||
| where T : new() | |||||
| { | |||||
| var type = typeof(T); | |||||
| var typeInfo = type.GetTypeInfo(); | |||||
| var action = _deserializers.GetOrAdd(type, _ => CreateDeserializer<T>(type, typeInfo)) as Func<ETFReader, T>; | |||||
| return action(this); | |||||
| } | |||||
| /*public void Read<T, U>() | |||||
| where T : Nullable<T> | |||||
| where U : struct, new() | |||||
| { | |||||
| }*/ | |||||
| public T[] ReadArray<T>() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public IDictionary<TKey, TValue> ReadDictionary<TKey, TValue>() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| /*public object Read(object obj) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| }*/ | |||||
| // public T Read<T>() | |||||
| // where T : new() | |||||
| // { | |||||
| // var type = typeof(T); | |||||
| // var typeInfo = type.GetTypeInfo(); | |||||
| // var action = _deserializers.GetOrAdd(type, _ => CreateDeserializer<T>(type, typeInfo)) as Func<ETFReader, T>; | |||||
| // return action(this); | |||||
| // } | |||||
| // /*public void Read<T, U>() | |||||
| // where T : Nullable<T> | |||||
| // where U : struct, new() | |||||
| // { | |||||
| // }*/ | |||||
| // public T[] ReadArray<T>() | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // } | |||||
| // public IDictionary<TKey, TValue> ReadDictionary<TKey, TValue>() | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // } | |||||
| // /*public object Read(object obj) | |||||
| // { | |||||
| // throw new NotImplementedException(); | |||||
| // }*/ | |||||
| private bool ReadNil(bool ignoreLength = false) | |||||
| { | |||||
| if (!ignoreLength) | |||||
| { | |||||
| _stream.Read(_buffer, 0, 1); | |||||
| byte length = _buffer[0]; | |||||
| if (length != 3) return false; | |||||
| } | |||||
| // private bool ReadNil(bool ignoreLength = false) | |||||
| // { | |||||
| // if (!ignoreLength) | |||||
| // { | |||||
| // _stream.Read(_buffer, 0, 1); | |||||
| // byte length = _buffer[0]; | |||||
| // if (length != 3) return false; | |||||
| // } | |||||
| _stream.Read(_buffer, 0, 3); | |||||
| if (_buffer[0] == 'n' && _buffer[1] == 'i' && _buffer[2] == 'l') | |||||
| return true; | |||||
| // _stream.Read(_buffer, 0, 3); | |||||
| // if (_buffer[0] == 'n' && _buffer[1] == 'i' && _buffer[2] == 'l') | |||||
| // return true; | |||||
| return false; | |||||
| } | |||||
| // return false; | |||||
| // } | |||||
| #region Emit | |||||
| private static Func<ETFReader, T> CreateDeserializer<T>(Type type, TypeInfo typeInfo) | |||||
| where T : new() | |||||
| { | |||||
| var method = new DynamicMethod("DeserializeETF", type, new[] { typeof(ETFReader) }, true); | |||||
| var generator = method.GetILGenerator(); | |||||
| // #region Emit | |||||
| // private static Func<ETFReader, T> CreateDeserializer<T>(Type type, TypeInfo typeInfo) | |||||
| // where T : new() | |||||
| // { | |||||
| // var method = new DynamicMethod("DeserializeETF", type, new[] { typeof(ETFReader) }, true); | |||||
| // var generator = method.GetILGenerator(); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| EmitReadValue(generator, type, typeInfo, true); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| // EmitReadValue(generator, type, typeInfo, true); | |||||
| generator.Emit(OpCodes.Ret); | |||||
| return method.CreateDelegate(typeof(Func<ETFReader, T>)) as Func<ETFReader, T>; | |||||
| } | |||||
| private static void EmitReadValue(ILGenerator generator, Type type, TypeInfo typeInfo, bool isTop) | |||||
| { | |||||
| //Convert enum types to their base type | |||||
| if (typeInfo.IsEnum) | |||||
| { | |||||
| type = Enum.GetUnderlyingType(type); | |||||
| typeInfo = type.GetTypeInfo(); | |||||
| } | |||||
| //Primitives/Enums | |||||
| if (!typeInfo.IsEnum && IsType(type, typeof(sbyte), typeof(byte), typeof(short), | |||||
| typeof(ushort), typeof(int), typeof(uint), typeof(long), | |||||
| typeof(ulong), typeof(double), typeof(bool), typeof(string), | |||||
| typeof(sbyte?), typeof(byte?), typeof(short?), typeof(ushort?), | |||||
| typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), | |||||
| typeof(bool?), typeof(float?), typeof(double?) | |||||
| /*typeof(object), typeof(DateTime)*/)) | |||||
| { | |||||
| //No conversion needed | |||||
| generator.EmitCall(OpCodes.Call, GetReadMethod(type), null); | |||||
| } | |||||
| //Dictionaries | |||||
| /*else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary<,>))) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeDictionaryTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Enumerable | |||||
| else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeEnumerableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Nullable Structs | |||||
| else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>) && | |||||
| typeInfo.GenericTypeParameters[0].GetTypeInfo().IsValueType) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeNullableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Structs/Classes | |||||
| else if (typeInfo.IsClass || (typeInfo.IsValueType && !typeInfo.IsPrimitive)) | |||||
| { | |||||
| if (isTop) | |||||
| { | |||||
| typeInfo.ForEachField(f => | |||||
| { | |||||
| string name; | |||||
| if (!f.IsPublic || !IsETFProperty(f, out name)) return; | |||||
| // generator.Emit(OpCodes.Ret); | |||||
| // return method.CreateDelegate(typeof(Func<ETFReader, T>)) as Func<ETFReader, T>; | |||||
| // } | |||||
| // private static void EmitReadValue(ILGenerator generator, Type type, TypeInfo typeInfo, bool isTop) | |||||
| // { | |||||
| // //Convert enum types to their base type | |||||
| // if (typeInfo.IsEnum) | |||||
| // { | |||||
| // type = Enum.GetUnderlyingType(type); | |||||
| // typeInfo = type.GetTypeInfo(); | |||||
| // } | |||||
| // //Primitives/Enums | |||||
| // if (!typeInfo.IsEnum && IsType(type, typeof(sbyte), typeof(byte), typeof(short), | |||||
| // typeof(ushort), typeof(int), typeof(uint), typeof(long), | |||||
| // typeof(ulong), typeof(double), typeof(bool), typeof(string), | |||||
| // typeof(sbyte?), typeof(byte?), typeof(short?), typeof(ushort?), | |||||
| // typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), | |||||
| // typeof(bool?), typeof(float?), typeof(double?) | |||||
| // /*typeof(object), typeof(DateTime)*/)) | |||||
| // { | |||||
| // //No conversion needed | |||||
| // generator.EmitCall(OpCodes.Call, GetReadMethod(type), null); | |||||
| // } | |||||
| // //Dictionaries | |||||
| // /*else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| // .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary<,>))) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeDictionaryTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Enumerable | |||||
| // else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| // .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeEnumerableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Nullable Structs | |||||
| // else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>) && | |||||
| // typeInfo.GenericTypeParameters[0].GetTypeInfo().IsValueType) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeNullableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Structs/Classes | |||||
| // else if (typeInfo.IsClass || (typeInfo.IsValueType && !typeInfo.IsPrimitive)) | |||||
| // { | |||||
| // if (isTop) | |||||
| // { | |||||
| // typeInfo.ForEachField(f => | |||||
| // { | |||||
| // string name; | |||||
| // if (!f.IsPublic || !IsETFProperty(f, out name)) return; | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| generator.Emit(OpCodes.Ldstr, name); //ETFReader(this), name | |||||
| generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| generator.Emit(OpCodes.Ldarg_1); //ETFReader(this), obj | |||||
| generator.Emit(OpCodes.Ldfld, f); //ETFReader(this), obj.fieldValue | |||||
| EmitWriteValue(generator, f.FieldType, f.FieldType.GetTypeInfo(), false); | |||||
| }); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| // generator.Emit(OpCodes.Ldstr, name); //ETFReader(this), name | |||||
| // generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| // generator.Emit(OpCodes.Ldarg_1); //ETFReader(this), obj | |||||
| // generator.Emit(OpCodes.Ldfld, f); //ETFReader(this), obj.fieldValue | |||||
| // EmitWriteValue(generator, f.FieldType, f.FieldType.GetTypeInfo(), false); | |||||
| // }); | |||||
| typeInfo.ForEachProperty(p => | |||||
| { | |||||
| string name; | |||||
| if (!p.CanRead || !p.GetMethod.IsPublic || !IsETFProperty(p, out name)) return; | |||||
| // typeInfo.ForEachProperty(p => | |||||
| // { | |||||
| // string name; | |||||
| // if (!p.CanRead || !p.GetMethod.IsPublic || !IsETFProperty(p, out name)) return; | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| generator.Emit(OpCodes.Ldstr, name); //ETFReader(this), name | |||||
| generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| generator.Emit(OpCodes.Ldarg_1); //ETFReader(this), obj | |||||
| generator.EmitCall(OpCodes.Callvirt, p.GetMethod, null); //ETFReader(this), obj.propValue | |||||
| EmitWriteValue(generator, p.PropertyType, p.PropertyType.GetTypeInfo(), false); | |||||
| }); | |||||
| } | |||||
| else | |||||
| { | |||||
| //While we could drill deeper and make a large serializer that also serializes all subclasses, | |||||
| //it's more efficient to serialize on a per-type basis via another Write<T> call. | |||||
| generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| }*/ | |||||
| //Unsupported (decimal, char) | |||||
| else | |||||
| throw new InvalidOperationException($"Deserializing {type.Name} is not supported."); | |||||
| } | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| // generator.Emit(OpCodes.Ldstr, name); //ETFReader(this), name | |||||
| // generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFReader(this) | |||||
| // generator.Emit(OpCodes.Ldarg_1); //ETFReader(this), obj | |||||
| // generator.EmitCall(OpCodes.Callvirt, p.GetMethod, null); //ETFReader(this), obj.propValue | |||||
| // EmitWriteValue(generator, p.PropertyType, p.PropertyType.GetTypeInfo(), false); | |||||
| // }); | |||||
| // } | |||||
| // else | |||||
| // { | |||||
| // //While we could drill deeper and make a large serializer that also serializes all subclasses, | |||||
| // //it's more efficient to serialize on a per-type basis via another Write<T> call. | |||||
| // generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // }*/ | |||||
| // //Unsupported (decimal, char) | |||||
| // else | |||||
| // throw new InvalidOperationException($"Deserializing {type.Name} is not supported."); | |||||
| // } | |||||
| private static bool IsType(Type type, params Type[] types) | |||||
| { | |||||
| for (int i = 0; i < types.Length; i++) | |||||
| { | |||||
| if (type == types[i]) | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| private static bool IsETFProperty(FieldInfo f, out string name) | |||||
| { | |||||
| var attrib = f.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| if (attrib != null) | |||||
| { | |||||
| name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? f.Name; | |||||
| return true; | |||||
| } | |||||
| name = null; | |||||
| return false; | |||||
| } | |||||
| private static bool IsETFProperty(PropertyInfo p, out string name) | |||||
| { | |||||
| var attrib = p.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| if (attrib != null) | |||||
| { | |||||
| name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? p.Name; | |||||
| return true; | |||||
| } | |||||
| name = null; | |||||
| return false; | |||||
| } | |||||
| // private static bool IsType(Type type, params Type[] types) | |||||
| // { | |||||
| // for (int i = 0; i < types.Length; i++) | |||||
| // { | |||||
| // if (type == types[i]) | |||||
| // return true; | |||||
| // } | |||||
| // return false; | |||||
| // } | |||||
| // private static bool IsETFProperty(FieldInfo f, out string name) | |||||
| // { | |||||
| // var attrib = f.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| // if (attrib != null) | |||||
| // { | |||||
| // name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? f.Name; | |||||
| // return true; | |||||
| // } | |||||
| // name = null; | |||||
| // return false; | |||||
| // } | |||||
| // private static bool IsETFProperty(PropertyInfo p, out string name) | |||||
| // { | |||||
| // var attrib = p.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| // if (attrib != null) | |||||
| // { | |||||
| // name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? p.Name; | |||||
| // return true; | |||||
| // } | |||||
| // name = null; | |||||
| // return false; | |||||
| // } | |||||
| private static MethodInfo GetReadMethod(string name) | |||||
| => typeof(ETFReader).GetTypeInfo().GetDeclaredMethods(name).Single(); | |||||
| private static MethodInfo GetReadMethod(Type type) | |||||
| { | |||||
| MethodInfo method; | |||||
| if (_readMethods.TryGetValue(type, out method)) | |||||
| return method; | |||||
| return null; | |||||
| } | |||||
| private static Dictionary<Type, MethodInfo> GetPrimitiveReadMethods() | |||||
| { | |||||
| return new Dictionary<Type, MethodInfo> | |||||
| { | |||||
| { typeof(bool), GetReadMethod(nameof(ReadBool)) }, | |||||
| { typeof(bool?), GetReadMethod(nameof(ReadNullableBool)) }, | |||||
| { typeof(byte), GetReadMethod(nameof(ReadByte)) }, | |||||
| { typeof(byte?), GetReadMethod(nameof(ReadNullableByte)) }, | |||||
| { typeof(sbyte), GetReadMethod(nameof(ReadSByte)) }, | |||||
| { typeof(sbyte?), GetReadMethod(nameof(ReadNullableSByte)) }, | |||||
| { typeof(short), GetReadMethod(nameof(ReadShort)) }, | |||||
| { typeof(short?), GetReadMethod(nameof(ReadNullableShort)) }, | |||||
| { typeof(ushort), GetReadMethod(nameof(ReadUShort)) }, | |||||
| { typeof(ushort?), GetReadMethod(nameof(ReadNullableUShort)) }, | |||||
| { typeof(int), GetReadMethod(nameof(ReadInt)) }, | |||||
| { typeof(int?), GetReadMethod(nameof(ReadNullableInt)) }, | |||||
| { typeof(uint), GetReadMethod(nameof(ReadUInt)) }, | |||||
| { typeof(uint?), GetReadMethod(nameof(ReadNullableUInt)) }, | |||||
| { typeof(long), GetReadMethod(nameof(ReadLong)) }, | |||||
| { typeof(long?), GetReadMethod(nameof(ReadNullableLong)) }, | |||||
| { typeof(ulong), GetReadMethod(nameof(ReadULong)) }, | |||||
| { typeof(ulong?), GetReadMethod(nameof(ReadNullableULong)) }, | |||||
| { typeof(float), GetReadMethod(nameof(ReadSingle)) }, | |||||
| { typeof(float?), GetReadMethod(nameof(ReadNullableSingle)) }, | |||||
| { typeof(double), GetReadMethod(nameof(ReadDouble)) }, | |||||
| { typeof(double?), GetReadMethod(nameof(ReadNullableDouble)) }, | |||||
| }; | |||||
| } | |||||
| #endregion | |||||
| // private static MethodInfo GetReadMethod(string name) | |||||
| // => typeof(ETFReader).GetTypeInfo().GetDeclaredMethods(name).Single(); | |||||
| // private static MethodInfo GetReadMethod(Type type) | |||||
| // { | |||||
| // MethodInfo method; | |||||
| // if (_readMethods.TryGetValue(type, out method)) | |||||
| // return method; | |||||
| // return null; | |||||
| // } | |||||
| // private static Dictionary<Type, MethodInfo> GetPrimitiveReadMethods() | |||||
| // { | |||||
| // return new Dictionary<Type, MethodInfo> | |||||
| // { | |||||
| // { typeof(bool), GetReadMethod(nameof(ReadBool)) }, | |||||
| // { typeof(bool?), GetReadMethod(nameof(ReadNullableBool)) }, | |||||
| // { typeof(byte), GetReadMethod(nameof(ReadByte)) }, | |||||
| // { typeof(byte?), GetReadMethod(nameof(ReadNullableByte)) }, | |||||
| // { typeof(sbyte), GetReadMethod(nameof(ReadSByte)) }, | |||||
| // { typeof(sbyte?), GetReadMethod(nameof(ReadNullableSByte)) }, | |||||
| // { typeof(short), GetReadMethod(nameof(ReadShort)) }, | |||||
| // { typeof(short?), GetReadMethod(nameof(ReadNullableShort)) }, | |||||
| // { typeof(ushort), GetReadMethod(nameof(ReadUShort)) }, | |||||
| // { typeof(ushort?), GetReadMethod(nameof(ReadNullableUShort)) }, | |||||
| // { typeof(int), GetReadMethod(nameof(ReadInt)) }, | |||||
| // { typeof(int?), GetReadMethod(nameof(ReadNullableInt)) }, | |||||
| // { typeof(uint), GetReadMethod(nameof(ReadUInt)) }, | |||||
| // { typeof(uint?), GetReadMethod(nameof(ReadNullableUInt)) }, | |||||
| // { typeof(long), GetReadMethod(nameof(ReadLong)) }, | |||||
| // { typeof(long?), GetReadMethod(nameof(ReadNullableLong)) }, | |||||
| // { typeof(ulong), GetReadMethod(nameof(ReadULong)) }, | |||||
| // { typeof(ulong?), GetReadMethod(nameof(ReadNullableULong)) }, | |||||
| // { typeof(float), GetReadMethod(nameof(ReadSingle)) }, | |||||
| // { typeof(float?), GetReadMethod(nameof(ReadNullableSingle)) }, | |||||
| // { typeof(double), GetReadMethod(nameof(ReadDouble)) }, | |||||
| // { typeof(double?), GetReadMethod(nameof(ReadNullableDouble)) }, | |||||
| // }; | |||||
| // } | |||||
| // #endregion | |||||
| #region IDisposable | |||||
| private bool _isDisposed = false; | |||||
| // #region IDisposable | |||||
| // private bool _isDisposed = false; | |||||
| protected virtual void Dispose(bool disposing) | |||||
| { | |||||
| if (!_isDisposed) | |||||
| { | |||||
| if (disposing) | |||||
| { | |||||
| if (_leaveOpen) | |||||
| _stream.Flush(); | |||||
| else | |||||
| _stream.Dispose(); | |||||
| } | |||||
| _isDisposed = true; | |||||
| } | |||||
| } | |||||
| // protected virtual void Dispose(bool disposing) | |||||
| // { | |||||
| // if (!_isDisposed) | |||||
| // { | |||||
| // if (disposing) | |||||
| // { | |||||
| // if (_leaveOpen) | |||||
| // _stream.Flush(); | |||||
| // else | |||||
| // _stream.Dispose(); | |||||
| // } | |||||
| // _isDisposed = true; | |||||
| // } | |||||
| // } | |||||
| public void Dispose() => Dispose(true); | |||||
| #endregion | |||||
| } | |||||
| } | |||||
| // public void Dispose() => Dispose(true); | |||||
| // #endregion | |||||
| // } | |||||
| //} | |||||
| @@ -1,482 +1,482 @@ | |||||
| using Newtonsoft.Json; | |||||
| using System; | |||||
| using System.Collections.Concurrent; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Linq; | |||||
| using System.Reflection; | |||||
| using System.Reflection.Emit; | |||||
| using System.Text; | |||||
| //using Newtonsoft.Json; | |||||
| //using System; | |||||
| //using System.Collections.Concurrent; | |||||
| //using System.Collections.Generic; | |||||
| //using System.IO; | |||||
| //using System.Linq; | |||||
| //using System.Reflection; | |||||
| //using System.Reflection.Emit; | |||||
| //using System.Text; | |||||
| namespace Discord.ETF | |||||
| { | |||||
| public unsafe class ETFWriter : IDisposable | |||||
| { | |||||
| private static readonly ConcurrentDictionary<Type, Delegate> _serializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| private static readonly ConcurrentDictionary<Type, Delegate> _indirectSerializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| //namespace Discord.ETF | |||||
| //{ | |||||
| // public unsafe class ETFWriter : IDisposable | |||||
| // { | |||||
| // private static readonly ConcurrentDictionary<Type, Delegate> _serializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| // private static readonly ConcurrentDictionary<Type, Delegate> _indirectSerializers = new ConcurrentDictionary<Type, Delegate>(); | |||||
| private static readonly byte[] _nilBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 3, (byte)'n', (byte)'i', (byte)'l' }; | |||||
| private static readonly byte[] _falseBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 5, (byte)'f', (byte)'a', (byte)'l', (byte)'s', (byte)'e' }; | |||||
| private static readonly byte[] _trueBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 4, (byte)'t', (byte)'r', (byte)'u', (byte)'e' }; | |||||
| // private static readonly byte[] _nilBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 3, (byte)'n', (byte)'i', (byte)'l' }; | |||||
| // private static readonly byte[] _falseBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 5, (byte)'f', (byte)'a', (byte)'l', (byte)'s', (byte)'e' }; | |||||
| // private static readonly byte[] _trueBytes = new byte[] { (byte)ETFType.SMALL_ATOM_EXT, 4, (byte)'t', (byte)'r', (byte)'u', (byte)'e' }; | |||||
| private static readonly MethodInfo _writeTMethod = GetGenericWriteMethod(null); | |||||
| private static readonly MethodInfo _writeNullableTMethod = GetGenericWriteMethod(typeof(Nullable<>)); | |||||
| private static readonly MethodInfo _writeDictionaryTMethod = GetGenericWriteMethod(typeof(IDictionary<,>)); | |||||
| private static readonly MethodInfo _writeEnumerableTMethod = GetGenericWriteMethod(typeof(IEnumerable<>)); | |||||
| private static readonly DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |||||
| // private static readonly MethodInfo _writeTMethod = GetGenericWriteMethod(null); | |||||
| // private static readonly MethodInfo _writeNullableTMethod = GetGenericWriteMethod(typeof(Nullable<>)); | |||||
| // private static readonly MethodInfo _writeDictionaryTMethod = GetGenericWriteMethod(typeof(IDictionary<,>)); | |||||
| // private static readonly MethodInfo _writeEnumerableTMethod = GetGenericWriteMethod(typeof(IEnumerable<>)); | |||||
| // private static readonly DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |||||
| private readonly Stream _stream; | |||||
| private readonly byte[] _buffer; | |||||
| private readonly bool _leaveOpen; | |||||
| private readonly Encoding _encoding; | |||||
| // private readonly Stream _stream; | |||||
| // private readonly byte[] _buffer; | |||||
| // private readonly bool _leaveOpen; | |||||
| // private readonly Encoding _encoding; | |||||
| public virtual Stream BaseStream | |||||
| { | |||||
| get | |||||
| { | |||||
| Flush(); | |||||
| return _stream; | |||||
| } | |||||
| } | |||||
| // public virtual Stream BaseStream | |||||
| // { | |||||
| // get | |||||
| // { | |||||
| // Flush(); | |||||
| // return _stream; | |||||
| // } | |||||
| // } | |||||
| public ETFWriter(Stream stream, bool leaveOpen = false) | |||||
| { | |||||
| if (stream == null) throw new ArgumentNullException(nameof(stream)); | |||||
| // public ETFWriter(Stream stream, bool leaveOpen = false) | |||||
| // { | |||||
| // if (stream == null) throw new ArgumentNullException(nameof(stream)); | |||||
| _stream = stream; | |||||
| _leaveOpen = leaveOpen; | |||||
| _buffer = new byte[11]; | |||||
| _encoding = Encoding.UTF8; | |||||
| } | |||||
| // _stream = stream; | |||||
| // _leaveOpen = leaveOpen; | |||||
| // _buffer = new byte[11]; | |||||
| // _encoding = Encoding.UTF8; | |||||
| // } | |||||
| public void Write(bool value) | |||||
| { | |||||
| if (value) | |||||
| _stream.Write(_trueBytes, 0, _trueBytes.Length); | |||||
| else | |||||
| _stream.Write(_falseBytes, 0, _falseBytes.Length); | |||||
| } | |||||
| public void Write(sbyte value) => Write((long)value); | |||||
| public void Write(byte value) => Write((ulong)value); | |||||
| public void Write(short value) => Write((long)value); | |||||
| public void Write(ushort value) => Write((ulong)value); | |||||
| public void Write(int value) => Write((long)value); | |||||
| public void Write(uint value) => Write((ulong)value); | |||||
| public void Write(long value) | |||||
| { | |||||
| if (value >= byte.MinValue && value <= byte.MaxValue) | |||||
| { | |||||
| _buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; | |||||
| _buffer[1] = (byte)value; | |||||
| _stream.Write(_buffer, 0, 2); | |||||
| } | |||||
| else if (value >= int.MinValue && value <= int.MaxValue) | |||||
| { | |||||
| //TODO: Does this encode negatives correctly? | |||||
| _buffer[0] = (byte)ETFType.INTEGER_EXT; | |||||
| _buffer[1] = (byte)(value >> 24); | |||||
| _buffer[2] = (byte)(value >> 16); | |||||
| _buffer[3] = (byte)(value >> 8); | |||||
| _buffer[4] = (byte)value; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| } | |||||
| else | |||||
| { | |||||
| _buffer[0] = (byte)ETFType.SMALL_BIG_EXT; | |||||
| if (value < 0) | |||||
| { | |||||
| _buffer[2] = 1; //Is negative | |||||
| value = -value; | |||||
| } | |||||
| // public void Write(bool value) | |||||
| // { | |||||
| // if (value) | |||||
| // _stream.Write(_trueBytes, 0, _trueBytes.Length); | |||||
| // else | |||||
| // _stream.Write(_falseBytes, 0, _falseBytes.Length); | |||||
| // } | |||||
| // public void Write(sbyte value) => Write((long)value); | |||||
| // public void Write(byte value) => Write((ulong)value); | |||||
| // public void Write(short value) => Write((long)value); | |||||
| // public void Write(ushort value) => Write((ulong)value); | |||||
| // public void Write(int value) => Write((long)value); | |||||
| // public void Write(uint value) => Write((ulong)value); | |||||
| // public void Write(long value) | |||||
| // { | |||||
| // if (value >= byte.MinValue && value <= byte.MaxValue) | |||||
| // { | |||||
| // _buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; | |||||
| // _buffer[1] = (byte)value; | |||||
| // _stream.Write(_buffer, 0, 2); | |||||
| // } | |||||
| // else if (value >= int.MinValue && value <= int.MaxValue) | |||||
| // { | |||||
| // //TODO: Does this encode negatives correctly? | |||||
| // _buffer[0] = (byte)ETFType.INTEGER_EXT; | |||||
| // _buffer[1] = (byte)(value >> 24); | |||||
| // _buffer[2] = (byte)(value >> 16); | |||||
| // _buffer[3] = (byte)(value >> 8); | |||||
| // _buffer[4] = (byte)value; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| // } | |||||
| // else | |||||
| // { | |||||
| // _buffer[0] = (byte)ETFType.SMALL_BIG_EXT; | |||||
| // if (value < 0) | |||||
| // { | |||||
| // _buffer[2] = 1; //Is negative | |||||
| // value = -value; | |||||
| // } | |||||
| byte bytes = 0; | |||||
| while (value > 0) | |||||
| _buffer[3 + bytes++] = (byte)(value >>= 8); | |||||
| _buffer[1] = bytes; //Encoded bytes | |||||
| // byte bytes = 0; | |||||
| // while (value > 0) | |||||
| // _buffer[3 + bytes++] = (byte)(value >>= 8); | |||||
| // _buffer[1] = bytes; //Encoded bytes | |||||
| _stream.Write(_buffer, 0, 3 + bytes); | |||||
| } | |||||
| } | |||||
| public void Write(ulong value) | |||||
| { | |||||
| if (value <= byte.MaxValue) | |||||
| { | |||||
| _buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; | |||||
| _buffer[1] = (byte)value; | |||||
| _stream.Write(_buffer, 0, 2); | |||||
| } | |||||
| else if (value <= int.MaxValue) | |||||
| { | |||||
| _buffer[0] = (byte)ETFType.INTEGER_EXT; | |||||
| _buffer[1] = (byte)(value >> 24); | |||||
| _buffer[2] = (byte)(value >> 16); | |||||
| _buffer[3] = (byte)(value >> 8); | |||||
| _buffer[4] = (byte)value; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| } | |||||
| else | |||||
| { | |||||
| _buffer[0] = (byte)ETFType.SMALL_BIG_EXT; | |||||
| _buffer[2] = 0; //Always positive | |||||
| // _stream.Write(_buffer, 0, 3 + bytes); | |||||
| // } | |||||
| // } | |||||
| // public void Write(ulong value) | |||||
| // { | |||||
| // if (value <= byte.MaxValue) | |||||
| // { | |||||
| // _buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; | |||||
| // _buffer[1] = (byte)value; | |||||
| // _stream.Write(_buffer, 0, 2); | |||||
| // } | |||||
| // else if (value <= int.MaxValue) | |||||
| // { | |||||
| // _buffer[0] = (byte)ETFType.INTEGER_EXT; | |||||
| // _buffer[1] = (byte)(value >> 24); | |||||
| // _buffer[2] = (byte)(value >> 16); | |||||
| // _buffer[3] = (byte)(value >> 8); | |||||
| // _buffer[4] = (byte)value; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| // } | |||||
| // else | |||||
| // { | |||||
| // _buffer[0] = (byte)ETFType.SMALL_BIG_EXT; | |||||
| // _buffer[2] = 0; //Always positive | |||||
| byte bytes = 0; | |||||
| while (value > 0) | |||||
| _buffer[3 + bytes++] = (byte)(value >>= 8); | |||||
| _buffer[1] = bytes; //Encoded bytes | |||||
| // byte bytes = 0; | |||||
| // while (value > 0) | |||||
| // _buffer[3 + bytes++] = (byte)(value >>= 8); | |||||
| // _buffer[1] = bytes; //Encoded bytes | |||||
| _stream.Write(_buffer, 0, 3 + bytes); | |||||
| } | |||||
| } | |||||
| // _stream.Write(_buffer, 0, 3 + bytes); | |||||
| // } | |||||
| // } | |||||
| public void Write(float value) => Write((double)value); | |||||
| public void Write(double value) | |||||
| { | |||||
| ulong value2 = *(ulong*)&value; | |||||
| _buffer[0] = (byte)ETFType.NEW_FLOAT_EXT; | |||||
| _buffer[1] = (byte)(value2 >> 56); | |||||
| _buffer[2] = (byte)(value2 >> 48); | |||||
| _buffer[3] = (byte)(value2 >> 40); | |||||
| _buffer[4] = (byte)(value2 >> 32); | |||||
| _buffer[5] = (byte)(value2 >> 24); | |||||
| _buffer[6] = (byte)(value2 >> 16); | |||||
| _buffer[7] = (byte)(value2 >> 8); | |||||
| _buffer[8] = (byte)value2; | |||||
| _stream.Write(_buffer, 0, 9); | |||||
| } | |||||
| // public void Write(float value) => Write((double)value); | |||||
| // public void Write(double value) | |||||
| // { | |||||
| // ulong value2 = *(ulong*)&value; | |||||
| // _buffer[0] = (byte)ETFType.NEW_FLOAT_EXT; | |||||
| // _buffer[1] = (byte)(value2 >> 56); | |||||
| // _buffer[2] = (byte)(value2 >> 48); | |||||
| // _buffer[3] = (byte)(value2 >> 40); | |||||
| // _buffer[4] = (byte)(value2 >> 32); | |||||
| // _buffer[5] = (byte)(value2 >> 24); | |||||
| // _buffer[6] = (byte)(value2 >> 16); | |||||
| // _buffer[7] = (byte)(value2 >> 8); | |||||
| // _buffer[8] = (byte)value2; | |||||
| // _stream.Write(_buffer, 0, 9); | |||||
| // } | |||||
| public void Write(DateTime value) => Write((ulong)((value.Ticks - _epochTime.Ticks) / TimeSpan.TicksPerSecond)); | |||||
| // public void Write(DateTime value) => Write((ulong)((value.Ticks - _epochTime.Ticks) / TimeSpan.TicksPerSecond)); | |||||
| public void Write(bool? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(sbyte? value) { if (value.HasValue) Write((long)value.Value); else WriteNil(); } | |||||
| public void Write(byte? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| public void Write(short? value) { if (value.HasValue) Write((long)value.Value); else WriteNil(); } | |||||
| public void Write(ushort? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| public void Write(int? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(uint? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| public void Write(long? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(ulong? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(double? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(float? value) { if (value.HasValue) Write((double)value.Value); else WriteNil(); } | |||||
| public void Write(DateTime? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(bool? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(sbyte? value) { if (value.HasValue) Write((long)value.Value); else WriteNil(); } | |||||
| // public void Write(byte? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| // public void Write(short? value) { if (value.HasValue) Write((long)value.Value); else WriteNil(); } | |||||
| // public void Write(ushort? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| // public void Write(int? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(uint? value) { if (value.HasValue) Write((ulong)value.Value); else WriteNil(); } | |||||
| // public void Write(long? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(ulong? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(double? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| // public void Write(float? value) { if (value.HasValue) Write((double)value.Value); else WriteNil(); } | |||||
| // public void Write(DateTime? value) { if (value.HasValue) Write(value.Value); else WriteNil(); } | |||||
| public void Write(string value) | |||||
| { | |||||
| if (value != null) | |||||
| { | |||||
| var bytes = _encoding.GetBytes(value); | |||||
| int count = bytes.Length; | |||||
| _buffer[0] = (byte)ETFType.BINARY_EXT; | |||||
| _buffer[1] = (byte)(count >> 24); | |||||
| _buffer[2] = (byte)(count >> 16); | |||||
| _buffer[3] = (byte)(count >> 8); | |||||
| _buffer[4] = (byte)count; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| _stream.Write(bytes, 0, bytes.Length); | |||||
| } | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| public void Write(byte[] value) | |||||
| { | |||||
| if (value != null) | |||||
| { | |||||
| int count = value.Length; | |||||
| _buffer[0] = (byte)ETFType.BINARY_EXT; | |||||
| _buffer[1] = (byte)(count >> 24); | |||||
| _buffer[2] = (byte)(count >> 16); | |||||
| _buffer[3] = (byte)(count >> 8); | |||||
| _buffer[4] = (byte)count; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| _stream.Write(value, 0, value.Length); | |||||
| } | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| // public void Write(string value) | |||||
| // { | |||||
| // if (value != null) | |||||
| // { | |||||
| // var bytes = _encoding.GetBytes(value); | |||||
| // int count = bytes.Length; | |||||
| // _buffer[0] = (byte)ETFType.BINARY_EXT; | |||||
| // _buffer[1] = (byte)(count >> 24); | |||||
| // _buffer[2] = (byte)(count >> 16); | |||||
| // _buffer[3] = (byte)(count >> 8); | |||||
| // _buffer[4] = (byte)count; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| // _stream.Write(bytes, 0, bytes.Length); | |||||
| // } | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| // public void Write(byte[] value) | |||||
| // { | |||||
| // if (value != null) | |||||
| // { | |||||
| // int count = value.Length; | |||||
| // _buffer[0] = (byte)ETFType.BINARY_EXT; | |||||
| // _buffer[1] = (byte)(count >> 24); | |||||
| // _buffer[2] = (byte)(count >> 16); | |||||
| // _buffer[3] = (byte)(count >> 8); | |||||
| // _buffer[4] = (byte)count; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| // _stream.Write(value, 0, value.Length); | |||||
| // } | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| public void Write<T>(T obj) | |||||
| { | |||||
| var type = typeof(T); | |||||
| var typeInfo = type.GetTypeInfo(); | |||||
| var action = _serializers.GetOrAdd(type, _ => CreateSerializer<T>(type, typeInfo, false)) as Action<ETFWriter, T>; | |||||
| action(this, obj); | |||||
| } | |||||
| public void Write<T>(T? obj) | |||||
| where T : struct | |||||
| { | |||||
| if (obj != null) | |||||
| Write(obj.Value); | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| public void Write<T>(IEnumerable<T> obj) | |||||
| { | |||||
| if (obj != null) | |||||
| { | |||||
| var array = obj.ToArray(); | |||||
| int length = array.Length; | |||||
| _buffer[0] = (byte)ETFType.LIST_EXT; | |||||
| _buffer[1] = (byte)(length >> 24); | |||||
| _buffer[2] = (byte)(length >> 16); | |||||
| _buffer[3] = (byte)(length >> 8); | |||||
| _buffer[4] = (byte)length; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| // public void Write<T>(T obj) | |||||
| // { | |||||
| // var type = typeof(T); | |||||
| // var typeInfo = type.GetTypeInfo(); | |||||
| // var action = _serializers.GetOrAdd(type, _ => CreateSerializer<T>(type, typeInfo, false)) as Action<ETFWriter, T>; | |||||
| // action(this, obj); | |||||
| // } | |||||
| // public void Write<T>(T? obj) | |||||
| // where T : struct | |||||
| // { | |||||
| // if (obj != null) | |||||
| // Write(obj.Value); | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| // public void Write<T>(IEnumerable<T> obj) | |||||
| // { | |||||
| // if (obj != null) | |||||
| // { | |||||
| // var array = obj.ToArray(); | |||||
| // int length = array.Length; | |||||
| // _buffer[0] = (byte)ETFType.LIST_EXT; | |||||
| // _buffer[1] = (byte)(length >> 24); | |||||
| // _buffer[2] = (byte)(length >> 16); | |||||
| // _buffer[3] = (byte)(length >> 8); | |||||
| // _buffer[4] = (byte)length; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| for (int i = 0; i < array.Length; i++) | |||||
| Write(array[i]); | |||||
| // for (int i = 0; i < array.Length; i++) | |||||
| // Write(array[i]); | |||||
| _buffer[0] = (byte)ETFType.NIL_EXT; | |||||
| _stream.Write(_buffer, 0, 1); | |||||
| } | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| public void Write<TKey, TValue>(IDictionary<TKey, TValue> obj) | |||||
| { | |||||
| if (obj != null) | |||||
| { | |||||
| int length = obj.Count; | |||||
| _buffer[0] = (byte)ETFType.MAP_EXT; | |||||
| _buffer[1] = (byte)(length >> 24); | |||||
| _buffer[2] = (byte)(length >> 16); | |||||
| _buffer[3] = (byte)(length >> 8); | |||||
| _buffer[4] = (byte)length; | |||||
| _stream.Write(_buffer, 0, 5); | |||||
| // _buffer[0] = (byte)ETFType.NIL_EXT; | |||||
| // _stream.Write(_buffer, 0, 1); | |||||
| // } | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| // public void Write<TKey, TValue>(IDictionary<TKey, TValue> obj) | |||||
| // { | |||||
| // if (obj != null) | |||||
| // { | |||||
| // int length = obj.Count; | |||||
| // _buffer[0] = (byte)ETFType.MAP_EXT; | |||||
| // _buffer[1] = (byte)(length >> 24); | |||||
| // _buffer[2] = (byte)(length >> 16); | |||||
| // _buffer[3] = (byte)(length >> 8); | |||||
| // _buffer[4] = (byte)length; | |||||
| // _stream.Write(_buffer, 0, 5); | |||||
| foreach (var pair in obj) | |||||
| { | |||||
| Write(pair.Key); | |||||
| Write(pair.Value); | |||||
| } | |||||
| } | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| public void Write(object obj) | |||||
| { | |||||
| if (obj != null) | |||||
| { | |||||
| var type = obj.GetType(); | |||||
| var typeInfo = type.GetTypeInfo(); | |||||
| var action = _indirectSerializers.GetOrAdd(type, _ => CreateSerializer<object>(type, typeInfo, true)) as Action<ETFWriter, object>; | |||||
| action(this, obj); | |||||
| } | |||||
| else | |||||
| WriteNil(); | |||||
| } | |||||
| // foreach (var pair in obj) | |||||
| // { | |||||
| // Write(pair.Key); | |||||
| // Write(pair.Value); | |||||
| // } | |||||
| // } | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| // public void Write(object obj) | |||||
| // { | |||||
| // if (obj != null) | |||||
| // { | |||||
| // var type = obj.GetType(); | |||||
| // var typeInfo = type.GetTypeInfo(); | |||||
| // var action = _indirectSerializers.GetOrAdd(type, _ => CreateSerializer<object>(type, typeInfo, true)) as Action<ETFWriter, object>; | |||||
| // action(this, obj); | |||||
| // } | |||||
| // else | |||||
| // WriteNil(); | |||||
| // } | |||||
| private void WriteNil() => _stream.Write(_nilBytes, 0, _nilBytes.Length); | |||||
| // private void WriteNil() => _stream.Write(_nilBytes, 0, _nilBytes.Length); | |||||
| public virtual void Flush() => _stream.Flush(); | |||||
| public virtual long Seek(int offset, SeekOrigin origin) => _stream.Seek(offset, origin); | |||||
| // public virtual void Flush() => _stream.Flush(); | |||||
| // public virtual long Seek(int offset, SeekOrigin origin) => _stream.Seek(offset, origin); | |||||
| #region Emit | |||||
| private static Action<ETFWriter, T> CreateSerializer<T>(Type type, TypeInfo typeInfo, bool isDirect) | |||||
| { | |||||
| var method = new DynamicMethod(isDirect ? "SerializeETF" : "SerializeIndirectETF", | |||||
| null, new[] { typeof(ETFWriter), isDirect ? type : typeof(object) }, true); | |||||
| var generator = method.GetILGenerator(); | |||||
| // #region Emit | |||||
| // private static Action<ETFWriter, T> CreateSerializer<T>(Type type, TypeInfo typeInfo, bool isDirect) | |||||
| // { | |||||
| // var method = new DynamicMethod(isDirect ? "SerializeETF" : "SerializeIndirectETF", | |||||
| // null, new[] { typeof(ETFWriter), isDirect ? type : typeof(object) }, true); | |||||
| // var generator = method.GetILGenerator(); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), value | |||||
| if (!isDirect) | |||||
| { | |||||
| if (typeInfo.IsValueType) //Unbox value types | |||||
| generator.Emit(OpCodes.Unbox_Any, type); //ETFWriter(this), real_value | |||||
| else //Cast reference types | |||||
| generator.Emit(OpCodes.Castclass, type); //ETFWriter(this), real_value | |||||
| generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(type), null); //Call generic version | |||||
| } | |||||
| else | |||||
| EmitWriteValue(generator, type, typeInfo, true); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| // generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), value | |||||
| // if (!isDirect) | |||||
| // { | |||||
| // if (typeInfo.IsValueType) //Unbox value types | |||||
| // generator.Emit(OpCodes.Unbox_Any, type); //ETFWriter(this), real_value | |||||
| // else //Cast reference types | |||||
| // generator.Emit(OpCodes.Castclass, type); //ETFWriter(this), real_value | |||||
| // generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(type), null); //Call generic version | |||||
| // } | |||||
| // else | |||||
| // EmitWriteValue(generator, type, typeInfo, true); | |||||
| generator.Emit(OpCodes.Ret); | |||||
| return method.CreateDelegate(typeof(Action<ETFWriter, T>)) as Action<ETFWriter, T>; | |||||
| } | |||||
| private static void EmitWriteValue(ILGenerator generator, Type type, TypeInfo typeInfo, bool isTop) | |||||
| { | |||||
| //Convert enum types to their base type | |||||
| if (typeInfo.IsEnum) | |||||
| { | |||||
| type = Enum.GetUnderlyingType(type); | |||||
| typeInfo = type.GetTypeInfo(); | |||||
| } | |||||
| // generator.Emit(OpCodes.Ret); | |||||
| // return method.CreateDelegate(typeof(Action<ETFWriter, T>)) as Action<ETFWriter, T>; | |||||
| // } | |||||
| // private static void EmitWriteValue(ILGenerator generator, Type type, TypeInfo typeInfo, bool isTop) | |||||
| // { | |||||
| // //Convert enum types to their base type | |||||
| // if (typeInfo.IsEnum) | |||||
| // { | |||||
| // type = Enum.GetUnderlyingType(type); | |||||
| // typeInfo = type.GetTypeInfo(); | |||||
| // } | |||||
| //Primitives/Enums | |||||
| Type targetType = null; | |||||
| if (!typeInfo.IsEnum && IsType(type, typeof(long), typeof(ulong), typeof(double), typeof(bool), typeof(string), | |||||
| typeof(sbyte?), typeof(byte?), typeof(short?), typeof(ushort?), | |||||
| typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), | |||||
| typeof(bool?), typeof(float?), typeof(double?), | |||||
| typeof(object), typeof(DateTime))) | |||||
| { | |||||
| //No conversion needed | |||||
| targetType = type; | |||||
| } | |||||
| else if (IsType(type, typeof(sbyte), typeof(short), typeof(int))) | |||||
| { | |||||
| //Convert to long | |||||
| generator.Emit(OpCodes.Conv_I8); | |||||
| targetType = typeof(long); | |||||
| } | |||||
| else if (IsType(type, typeof(byte), typeof(ushort), typeof(uint))) | |||||
| { | |||||
| //Convert to ulong | |||||
| generator.Emit(OpCodes.Conv_U8); | |||||
| targetType = typeof(ulong); | |||||
| } | |||||
| else if (IsType(type, typeof(float))) | |||||
| { | |||||
| //Convert to double | |||||
| generator.Emit(OpCodes.Conv_R8); | |||||
| targetType = typeof(double); | |||||
| } | |||||
| if (targetType != null) | |||||
| generator.EmitCall(OpCodes.Call, GetWriteMethod(targetType), null); | |||||
| // //Primitives/Enums | |||||
| // Type targetType = null; | |||||
| // if (!typeInfo.IsEnum && IsType(type, typeof(long), typeof(ulong), typeof(double), typeof(bool), typeof(string), | |||||
| // typeof(sbyte?), typeof(byte?), typeof(short?), typeof(ushort?), | |||||
| // typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), | |||||
| // typeof(bool?), typeof(float?), typeof(double?), | |||||
| // typeof(object), typeof(DateTime))) | |||||
| // { | |||||
| // //No conversion needed | |||||
| // targetType = type; | |||||
| // } | |||||
| // else if (IsType(type, typeof(sbyte), typeof(short), typeof(int))) | |||||
| // { | |||||
| // //Convert to long | |||||
| // generator.Emit(OpCodes.Conv_I8); | |||||
| // targetType = typeof(long); | |||||
| // } | |||||
| // else if (IsType(type, typeof(byte), typeof(ushort), typeof(uint))) | |||||
| // { | |||||
| // //Convert to ulong | |||||
| // generator.Emit(OpCodes.Conv_U8); | |||||
| // targetType = typeof(ulong); | |||||
| // } | |||||
| // else if (IsType(type, typeof(float))) | |||||
| // { | |||||
| // //Convert to double | |||||
| // generator.Emit(OpCodes.Conv_R8); | |||||
| // targetType = typeof(double); | |||||
| // } | |||||
| // if (targetType != null) | |||||
| // generator.EmitCall(OpCodes.Call, GetWriteMethod(targetType), null); | |||||
| //Dictionaries | |||||
| else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary<,>))) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeDictionaryTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Enumerable | |||||
| else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeEnumerableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Nullable Structs | |||||
| else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>) && | |||||
| typeInfo.GenericTypeParameters[0].GetTypeInfo().IsValueType) | |||||
| { | |||||
| generator.EmitCall(OpCodes.Call, _writeNullableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| //Structs/Classes | |||||
| else if (typeInfo.IsClass || (typeInfo.IsValueType && !typeInfo.IsPrimitive)) | |||||
| { | |||||
| if (isTop) | |||||
| { | |||||
| typeInfo.ForEachField(f => | |||||
| { | |||||
| string name; | |||||
| if (!f.IsPublic || !IsETFProperty(f, out name)) return; | |||||
| // //Dictionaries | |||||
| // else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| // .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary<,>))) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeDictionaryTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Enumerable | |||||
| // else if (!typeInfo.IsValueType && typeInfo.ImplementedInterfaces | |||||
| // .Any(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeEnumerableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Nullable Structs | |||||
| // else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>) && | |||||
| // typeInfo.GenericTypeParameters[0].GetTypeInfo().IsValueType) | |||||
| // { | |||||
| // generator.EmitCall(OpCodes.Call, _writeNullableTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // //Structs/Classes | |||||
| // else if (typeInfo.IsClass || (typeInfo.IsValueType && !typeInfo.IsPrimitive)) | |||||
| // { | |||||
| // if (isTop) | |||||
| // { | |||||
| // typeInfo.ForEachField(f => | |||||
| // { | |||||
| // string name; | |||||
| // if (!f.IsPublic || !IsETFProperty(f, out name)) return; | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| generator.Emit(OpCodes.Ldstr, name); //ETFWriter(this), name | |||||
| generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), obj | |||||
| generator.Emit(OpCodes.Ldfld, f); //ETFWriter(this), obj.fieldValue | |||||
| EmitWriteValue(generator, f.FieldType, f.FieldType.GetTypeInfo(), false); | |||||
| }); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| // generator.Emit(OpCodes.Ldstr, name); //ETFWriter(this), name | |||||
| // generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| // generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), obj | |||||
| // generator.Emit(OpCodes.Ldfld, f); //ETFWriter(this), obj.fieldValue | |||||
| // EmitWriteValue(generator, f.FieldType, f.FieldType.GetTypeInfo(), false); | |||||
| // }); | |||||
| typeInfo.ForEachProperty(p => | |||||
| { | |||||
| string name; | |||||
| if (!p.CanRead || !p.GetMethod.IsPublic || !IsETFProperty(p, out name)) return; | |||||
| // typeInfo.ForEachProperty(p => | |||||
| // { | |||||
| // string name; | |||||
| // if (!p.CanRead || !p.GetMethod.IsPublic || !IsETFProperty(p, out name)) return; | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| generator.Emit(OpCodes.Ldstr, name); //ETFWriter(this), name | |||||
| generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), obj | |||||
| generator.EmitCall(OpCodes.Callvirt, p.GetMethod, null); //ETFWriter(this), obj.propValue | |||||
| EmitWriteValue(generator, p.PropertyType, p.PropertyType.GetTypeInfo(), false); | |||||
| }); | |||||
| } | |||||
| else | |||||
| { | |||||
| //While we could drill deeper and make a large serializer that also serializes all subclasses, | |||||
| //it's more efficient to serialize on a per-type basis via another Write<T> call. | |||||
| generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| } | |||||
| } | |||||
| //Unsupported (decimal, char) | |||||
| else | |||||
| throw new InvalidOperationException($"Serializing {type.Name} is not supported."); | |||||
| } | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| // generator.Emit(OpCodes.Ldstr, name); //ETFWriter(this), name | |||||
| // generator.EmitCall(OpCodes.Call, GetWriteMethod(typeof(string)), null); | |||||
| // generator.Emit(OpCodes.Ldarg_0); //ETFWriter(this) | |||||
| // generator.Emit(OpCodes.Ldarg_1); //ETFWriter(this), obj | |||||
| // generator.EmitCall(OpCodes.Callvirt, p.GetMethod, null); //ETFWriter(this), obj.propValue | |||||
| // EmitWriteValue(generator, p.PropertyType, p.PropertyType.GetTypeInfo(), false); | |||||
| // }); | |||||
| // } | |||||
| // else | |||||
| // { | |||||
| // //While we could drill deeper and make a large serializer that also serializes all subclasses, | |||||
| // //it's more efficient to serialize on a per-type basis via another Write<T> call. | |||||
| // generator.EmitCall(OpCodes.Call, _writeTMethod.MakeGenericMethod(typeInfo.GenericTypeParameters), null); | |||||
| // } | |||||
| // } | |||||
| // //Unsupported (decimal, char) | |||||
| // else | |||||
| // throw new InvalidOperationException($"Serializing {type.Name} is not supported."); | |||||
| // } | |||||
| private static bool IsType(Type type, params Type[] types) | |||||
| { | |||||
| for (int i = 0; i < types.Length; i++) | |||||
| { | |||||
| if (type == types[i]) | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| private static bool IsETFProperty(FieldInfo f, out string name) | |||||
| { | |||||
| var attrib = f.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| if (attrib != null) | |||||
| { | |||||
| name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? f.Name; | |||||
| return true; | |||||
| } | |||||
| name = null; | |||||
| return false; | |||||
| } | |||||
| private static bool IsETFProperty(PropertyInfo p, out string name) | |||||
| { | |||||
| var attrib = p.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| if (attrib != null) | |||||
| { | |||||
| name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? p.Name; | |||||
| return true; | |||||
| } | |||||
| name = null; | |||||
| return false; | |||||
| } | |||||
| // private static bool IsType(Type type, params Type[] types) | |||||
| // { | |||||
| // for (int i = 0; i < types.Length; i++) | |||||
| // { | |||||
| // if (type == types[i]) | |||||
| // return true; | |||||
| // } | |||||
| // return false; | |||||
| // } | |||||
| // private static bool IsETFProperty(FieldInfo f, out string name) | |||||
| // { | |||||
| // var attrib = f.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| // if (attrib != null) | |||||
| // { | |||||
| // name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? f.Name; | |||||
| // return true; | |||||
| // } | |||||
| // name = null; | |||||
| // return false; | |||||
| // } | |||||
| // private static bool IsETFProperty(PropertyInfo p, out string name) | |||||
| // { | |||||
| // var attrib = p.CustomAttributes.Where(x => x.AttributeType == typeof(JsonPropertyAttribute)).FirstOrDefault(); | |||||
| // if (attrib != null) | |||||
| // { | |||||
| // name = attrib.ConstructorArguments.FirstOrDefault().Value as string ?? p.Name; | |||||
| // return true; | |||||
| // } | |||||
| // name = null; | |||||
| // return false; | |||||
| // } | |||||
| private static MethodInfo GetWriteMethod(Type paramType) | |||||
| { | |||||
| return typeof(ETFWriter).GetTypeInfo().GetDeclaredMethods(nameof(Write)) | |||||
| .Where(x => x.GetParameters()[0].ParameterType == paramType) | |||||
| .Single(); | |||||
| } | |||||
| private static MethodInfo GetGenericWriteMethod(Type genericType) | |||||
| { | |||||
| if (genericType == null) | |||||
| { | |||||
| return typeof(ETFWriter).GetTypeInfo() | |||||
| .GetDeclaredMethods(nameof(Write)) | |||||
| .Where(x => x.IsGenericMethodDefinition && x.GetParameters()[0].ParameterType == x.GetGenericArguments()[0]) | |||||
| .Single(); | |||||
| } | |||||
| else | |||||
| { | |||||
| return typeof(ETFWriter).GetTypeInfo() | |||||
| .GetDeclaredMethods(nameof(Write)) | |||||
| .Where(x => | |||||
| { | |||||
| if (!x.IsGenericMethodDefinition) return false; | |||||
| var p = x.GetParameters()[0].ParameterType.GetTypeInfo(); | |||||
| return p.IsGenericType && p.GetGenericTypeDefinition() == genericType; | |||||
| }) | |||||
| .Single(); | |||||
| } | |||||
| } | |||||
| #endregion | |||||
| // private static MethodInfo GetWriteMethod(Type paramType) | |||||
| // { | |||||
| // return typeof(ETFWriter).GetTypeInfo().GetDeclaredMethods(nameof(Write)) | |||||
| // .Where(x => x.GetParameters()[0].ParameterType == paramType) | |||||
| // .Single(); | |||||
| // } | |||||
| // private static MethodInfo GetGenericWriteMethod(Type genericType) | |||||
| // { | |||||
| // if (genericType == null) | |||||
| // { | |||||
| // return typeof(ETFWriter).GetTypeInfo() | |||||
| // .GetDeclaredMethods(nameof(Write)) | |||||
| // .Where(x => x.IsGenericMethodDefinition && x.GetParameters()[0].ParameterType == x.GetGenericArguments()[0]) | |||||
| // .Single(); | |||||
| // } | |||||
| // else | |||||
| // { | |||||
| // return typeof(ETFWriter).GetTypeInfo() | |||||
| // .GetDeclaredMethods(nameof(Write)) | |||||
| // .Where(x => | |||||
| // { | |||||
| // if (!x.IsGenericMethodDefinition) return false; | |||||
| // var p = x.GetParameters()[0].ParameterType.GetTypeInfo(); | |||||
| // return p.IsGenericType && p.GetGenericTypeDefinition() == genericType; | |||||
| // }) | |||||
| // .Single(); | |||||
| // } | |||||
| // } | |||||
| // #endregion | |||||
| #region IDisposable | |||||
| private bool _isDisposed = false; | |||||
| // #region IDisposable | |||||
| // private bool _isDisposed = false; | |||||
| protected virtual void Dispose(bool disposing) | |||||
| { | |||||
| if (!_isDisposed) | |||||
| { | |||||
| if (disposing) | |||||
| { | |||||
| if (_leaveOpen) | |||||
| _stream.Flush(); | |||||
| else | |||||
| _stream.Dispose(); | |||||
| } | |||||
| _isDisposed = true; | |||||
| } | |||||
| } | |||||
| // protected virtual void Dispose(bool disposing) | |||||
| // { | |||||
| // if (!_isDisposed) | |||||
| // { | |||||
| // if (disposing) | |||||
| // { | |||||
| // if (_leaveOpen) | |||||
| // _stream.Flush(); | |||||
| // else | |||||
| // _stream.Dispose(); | |||||
| // } | |||||
| // _isDisposed = true; | |||||
| // } | |||||
| // } | |||||
| public void Dispose() => Dispose(true); | |||||
| #endregion | |||||
| } | |||||
| } | |||||
| // public void Dispose() => Dispose(true); | |||||
| // #endregion | |||||
| // } | |||||
| //} | |||||
| @@ -7,36 +7,36 @@ namespace Discord.Logging | |||||
| LogSeverity Level { get; } | LogSeverity Level { get; } | ||||
| void Log(LogSeverity severity, string message, Exception exception = null); | void Log(LogSeverity severity, string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Log(LogSeverity severity, FormattableString message, Exception exception = null); | void Log(LogSeverity severity, FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Error(string message, Exception exception = null); | void Error(string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Error(FormattableString message, Exception exception = null); | void Error(FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Error(Exception exception); | void Error(Exception exception); | ||||
| void Warning(string message, Exception exception = null); | void Warning(string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Warning(FormattableString message, Exception exception = null); | void Warning(FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Warning(Exception exception); | void Warning(Exception exception); | ||||
| void Info(string message, Exception exception = null); | void Info(string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Info(FormattableString message, Exception exception = null); | void Info(FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Info(Exception exception); | void Info(Exception exception); | ||||
| void Verbose(string message, Exception exception = null); | void Verbose(string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Verbose(FormattableString message, Exception exception = null); | void Verbose(FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Verbose(Exception exception); | void Verbose(Exception exception); | ||||
| void Debug(string message, Exception exception = null); | void Debug(string message, Exception exception = null); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| void Debug(FormattableString message, Exception exception = null); | void Debug(FormattableString message, Exception exception = null); | ||||
| #endif | #endif | ||||
| void Debug(Exception exception); | void Debug(Exception exception); | ||||
| @@ -25,7 +25,7 @@ namespace Discord.Logging | |||||
| } | } | ||||
| } | } | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| public void Log(LogSeverity severity, string source, FormattableString message, Exception exception = null) | public void Log(LogSeverity severity, string source, FormattableString message, Exception exception = null) | ||||
| { | { | ||||
| if (severity <= Level) | if (severity <= Level) | ||||
| @@ -57,7 +57,7 @@ namespace Discord.Logging | |||||
| public void Debug(string source, Exception ex) | public void Debug(string source, Exception ex) | ||||
| => Log(LogSeverity.Debug, source, (string)null, ex); | => Log(LogSeverity.Debug, source, (string)null, ex); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| public void Error(string source, FormattableString message, Exception ex = null) | public void Error(string source, FormattableString message, Exception ex = null) | ||||
| => Log(LogSeverity.Error, source, message, ex); | => Log(LogSeverity.Error, source, message, ex); | ||||
| public void Warning(string source, FormattableString message, Exception ex = null) | public void Warning(string source, FormattableString message, Exception ex = null) | ||||
| @@ -38,7 +38,7 @@ namespace Discord.Logging | |||||
| public void Debug(Exception exception) | public void Debug(Exception exception) | ||||
| => _manager.Debug(Name, exception); | => _manager.Debug(Name, exception); | ||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| public void Log(LogSeverity severity, FormattableString message, Exception exception = null) | public void Log(LogSeverity severity, FormattableString message, Exception exception = null) | ||||
| => _manager.Log(severity, Name, message, exception); | => _manager.Log(severity, Name, message, exception); | ||||
| public void Error(FormattableString message, Exception exception = null) | public void Error(FormattableString message, Exception exception = null) | ||||
| @@ -1,4 +1,4 @@ | |||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| using Discord.Logging; | using Discord.Logging; | ||||
| using System; | using System; | ||||
| using System.IO; | using System.IO; | ||||
| @@ -1,27 +0,0 @@ | |||||
| using Discord.ETF; | |||||
| using System.IO; | |||||
| using System; | |||||
| using Discord.Logging; | |||||
| namespace Discord.Net.Rest | |||||
| { | |||||
| public class ETFRestClient : RestClient | |||||
| { | |||||
| private readonly ETFWriter _serializer; | |||||
| public ETFRestClient(DiscordConfig config, string baseUrl, ILogger logger = null) | |||||
| : base(config, baseUrl, logger) | |||||
| { | |||||
| _serializer = new ETFWriter(new MemoryStream()); | |||||
| } | |||||
| protected override string Serialize<T>(T obj) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| protected override T Deserialize<T>(string json) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -36,7 +36,6 @@ namespace Discord.Net.Rest | |||||
| private readonly DiscordConfig _config; | private readonly DiscordConfig _config; | ||||
| private readonly IRestEngine _engine; | private readonly IRestEngine _engine; | ||||
| private readonly ETFWriter _serializer; | |||||
| private readonly ILogger _logger; | private readonly ILogger _logger; | ||||
| private string _token; | private string _token; | ||||
| @@ -57,7 +56,7 @@ namespace Discord.Net.Rest | |||||
| _config = config; | _config = config; | ||||
| _logger = logger; | _logger = logger; | ||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| _engine = new RestSharpEngine(config, baseUrl, logger); | _engine = new RestSharpEngine(config, baseUrl, logger); | ||||
| #else | #else | ||||
| _engine = new BuiltInEngine(config, baseUrl, logger); | _engine = new BuiltInEngine(config, baseUrl, logger); | ||||
| @@ -1,4 +1,4 @@ | |||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| using Discord.Logging; | using Discord.Logging; | ||||
| using Nito.AsyncEx; | using Nito.AsyncEx; | ||||
| using RestSharp; | using RestSharp; | ||||
| @@ -1,4 +1,4 @@ | |||||
| #if DOTNET5_4 | |||||
| #if NETSTANDARD1_3 | |||||
| using System; | using System; | ||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| @@ -89,7 +89,7 @@ namespace Discord.Net.WebSockets | |||||
| if (result.MessageType == WebSocketMessageType.Close) | if (result.MessageType == WebSocketMessageType.Close) | ||||
| throw new WebSocketException((int)result.CloseStatus.Value, result.CloseStatusDescription); | throw new WebSocketException((int)result.CloseStatus.Value, result.CloseStatusDescription); | ||||
| else | else | ||||
| stream.Write(buffer.Array, buffer.Offset, buffer.Count); | |||||
| stream.Write(buffer.Array, 0, result.Count); | |||||
| } | } | ||||
| while (result == null || !result.EndOfMessage); | while (result == null || !result.EndOfMessage); | ||||
| @@ -1,4 +1,4 @@ | |||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| using SuperSocket.ClientEngine; | using SuperSocket.ClientEngine; | ||||
| using System; | using System; | ||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
| @@ -49,7 +49,7 @@ namespace Discord.Net.WebSockets | |||||
| CancelToken = new CancellationToken(true); | CancelToken = new CancellationToken(true); | ||||
| _connectedEvent = new ManualResetEventSlim(false); | _connectedEvent = new ManualResetEventSlim(false); | ||||
| #if !DOTNET5_4 | |||||
| #if !NETSTANDARD1_3 | |||||
| _engine = new WS4NetEngine(config, _taskManager); | _engine = new WS4NetEngine(config, _taskManager); | ||||
| #else | #else | ||||
| _engine = new BuiltInEngine(config); | _engine = new BuiltInEngine(config); | ||||
| @@ -1,29 +1,31 @@ | |||||
| { | { | ||||
| "version": "0.9.1", | "version": "0.9.1", | ||||
| "description": "An unofficial .Net API wrapper for the Discord client.", | "description": "An unofficial .Net API wrapper for the Discord client.", | ||||
| "authors": [ | |||||
| "RogueException" | |||||
| ], | |||||
| "tags": [ | |||||
| "discord", | |||||
| "discordapp" | |||||
| ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| "authors": [ "RogueException" ], | |||||
| "packOptions": { | |||||
| "tags": [ | |||||
| "discord", | |||||
| "discordapp" | |||||
| ], | |||||
| "projectUrl": "https://github.com/RogueException/Discord.Net", | |||||
| "licenseUrl": "http://opensource.org/licenses/MIT", | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git://github.com/RogueException/Discord.Net" | |||||
| } | |||||
| }, | }, | ||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "compilationOptions": { | |||||
| "buildOptions": { | |||||
| "compile": [ "**/*.cs", "../Discord.Net.Shared/*.cs" ], | |||||
| "preserveCompilationContext": true, | |||||
| "allowUnsafe": true, | "allowUnsafe": true, | ||||
| "warningsAsErrors": true | "warningsAsErrors": true | ||||
| }, | }, | ||||
| "configurations": { | "configurations": { | ||||
| "TestResponses": { | "TestResponses": { | ||||
| "compilationOptions": { | |||||
| "buildOptions": { | |||||
| "define": [ | "define": [ | ||||
| "DEBUG", | "DEBUG", | ||||
| "TRACE", | "TRACE", | ||||
| @@ -34,48 +36,24 @@ | |||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "Newtonsoft.Json": "8.0.1", | |||||
| "Nito.AsyncEx": "3.0.1" | |||||
| "NETStandard.Library": "1.5.0-rc2-24027", | |||||
| "Newtonsoft.Json": "8.0.3", | |||||
| "Nito.AsyncEx": "3.0.1", | |||||
| "System.Net.Requests": "4.0.11-rc2-24027", | |||||
| "System.Net.Websockets.Client": "4.0.0-rc2-24027", | |||||
| "System.Reflection.Emit.Lightweight": "4.0.1-rc2-24027", | |||||
| "System.Runtime.Serialization.Primitives": "4.1.1-rc2-24027", | |||||
| "System.Security.Cryptography.Algorithms": "4.1.0-rc2-24027", | |||||
| "System.Net.NameResolution": "4.0.0-rc2-24027" | |||||
| }, | }, | ||||
| "frameworks": { | "frameworks": { | ||||
| "dotnet5.4": { | |||||
| "dependencies": { | |||||
| "System.Collections": "4.0.11-beta-23516", | |||||
| "System.Collections.Concurrent": "4.0.11-beta-23516", | |||||
| "System.Dynamic.Runtime": "4.0.11-beta-23516", | |||||
| "System.IO.FileSystem": "4.0.1-beta-23516", | |||||
| "System.IO.Compression": "4.1.0-beta-23516", | |||||
| "System.Linq": "4.0.1-beta-23516", | |||||
| "System.Net.Http": "4.0.1-beta-23516", | |||||
| "System.Net.NameResolution": "4.0.0-beta-23516", | |||||
| "System.Net.Sockets": "4.1.0-beta-23409", | |||||
| "System.Net.Requests": "4.0.11-beta-23516", | |||||
| "System.Net.WebSockets.Client": "4.0.0-beta-23516", | |||||
| "System.Reflection": "4.1.0-beta-23516", | |||||
| "System.Reflection.Emit.Lightweight": "4.0.1-beta-23516", | |||||
| "System.Runtime.InteropServices": "4.0.21-beta-23516", | |||||
| "System.Runtime.Serialization.Primitives": "4.1.0-beta-23516", | |||||
| "System.Security.Cryptography.Algorithms": "4.0.0-beta-23516", | |||||
| "System.Text.RegularExpressions": "4.0.11-beta-23516", | |||||
| "System.Threading": "4.0.11-beta-23516" | |||||
| } | |||||
| }, | |||||
| "net45": { | |||||
| "frameworkAssemblies": { | |||||
| "System.Runtime": { | |||||
| "type": "build", | |||||
| "version": "" | |||||
| }, | |||||
| "System.Threading.Tasks": { | |||||
| "type": "build", | |||||
| "version": "" | |||||
| } | |||||
| }, | |||||
| "dependencies": { | |||||
| "WebSocket4Net": "0.14.1", | |||||
| "RestSharp": "105.2.3" | |||||
| } | |||||
| "netstandard1.3": { | |||||
| "imports": [ | |||||
| "dotnet5.4", | |||||
| "dnxcore50", | |||||
| "portable-net45+win8" | |||||
| ] | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -58,15 +58,15 @@ | |||||
| <Compile Include="Tests.cs" /> | <Compile Include="Tests.cs" /> | ||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <None Include="packages.config" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | <ItemGroup> | ||||
| <ProjectReference Include="..\..\src\Discord.Net.Net45\Discord.Net.csproj"> | <ProjectReference Include="..\..\src\Discord.Net.Net45\Discord.Net.csproj"> | ||||
| <Project>{8d71a857-879a-4a10-859e-5ff824ed6688}</Project> | <Project>{8d71a857-879a-4a10-859e-5ff824ed6688}</Project> | ||||
| <Name>Discord.Net</Name> | <Name>Discord.Net</Name> | ||||
| </ProjectReference> | </ProjectReference> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <None Include="packages.config" /> | |||||
| </ItemGroup> | |||||
| <Choose> | <Choose> | ||||
| <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> | <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| @@ -334,7 +334,7 @@ namespace Discord.Tests | |||||
| async () => await SetGame(_targetBot, "test game"), | async () => await SetGame(_targetBot, "test game"), | ||||
| x => _observerBot.UserUpdated += x, | x => _observerBot.UserUpdated += x, | ||||
| x => _observerBot.UserUpdated -= x, | x => _observerBot.UserUpdated -= x, | ||||
| (s, e) => _targetBot.CurrentGame == "test game"); | |||||
| (s, e) => _targetBot.CurrentGame.Name == "test game"); | |||||
| } | } | ||||
| private async Task SetGame(DiscordClient _client, string game) | private async Task SetGame(DiscordClient _client, string game) | ||||