@@ -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" | |||||
] | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -59,14 +59,14 @@ | |||||
<Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<None Include="packages.config" /> | |||||
</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) | ||||