Json (de)serilazion works with some tests
This commit is contained in:
parent
b4540af9db
commit
a7a087b637
31
Discord.API.Tests/Discord.API.Tests.csproj
Normal file
31
Discord.API.Tests/Discord.API.Tests.csproj
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
|
||||||
|
<PackageReference Include="xunit" Version="2.5.3"/>
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Discord.API\Discord.API.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
149
Discord.API.Tests/JsonTests.cs
Normal file
149
Discord.API.Tests/JsonTests.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Discord.API.Tests;
|
||||||
|
using Xunit;
|
||||||
|
using Discord.API;
|
||||||
|
|
||||||
|
public class JsonTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GatewayPacketEncodeJsonTest()
|
||||||
|
{
|
||||||
|
var gateway_packet = new GatewayPacket()
|
||||||
|
{
|
||||||
|
Op = GatewayPacket.Opcode.Heartbeat
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonSerializer.Serialize(gateway_packet, SourceGenerationContext.Default.GatewayPacket);
|
||||||
|
|
||||||
|
Assert.Equal("""{"op":1}""", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GatewayPacketDecodeTest()
|
||||||
|
{
|
||||||
|
const string src = """{"op":1}""";
|
||||||
|
var gateway_packet =
|
||||||
|
JsonSerializer.Deserialize<GatewayPacket>(src, SourceGenerationContext.Default.GatewayPacket);
|
||||||
|
Assert.Equal(GatewayPacket.Opcode.Heartbeat, gateway_packet?.Op);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadyPacketDeserialize()
|
||||||
|
{
|
||||||
|
const string src = """
|
||||||
|
{
|
||||||
|
"op":0,
|
||||||
|
"t":"READY",
|
||||||
|
"s":1,
|
||||||
|
"d":{
|
||||||
|
"v":10,
|
||||||
|
"user":{
|
||||||
|
"id":"1234",
|
||||||
|
"username":"abrakadabra",
|
||||||
|
"discriminator":"1111",
|
||||||
|
"global_name":"glblname"
|
||||||
|
},
|
||||||
|
"guilds":[
|
||||||
|
{
|
||||||
|
"id":"5678",
|
||||||
|
"unavailable":true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"session_id":"abcd",
|
||||||
|
"resume_gateway_url":"dfgh",
|
||||||
|
"application":{
|
||||||
|
"id":"3333",
|
||||||
|
"flags":5555
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
GatewayPacket? packet =
|
||||||
|
JsonSerializer.Deserialize<GatewayPacket>(src, SourceGenerationContext.Default.GatewayPacket);
|
||||||
|
|
||||||
|
Assert.NotNull(packet);
|
||||||
|
Assert.IsType<ReadyPacket>(packet);
|
||||||
|
|
||||||
|
Assert.True(packet is ReadyPacket
|
||||||
|
{
|
||||||
|
Op: GatewayPacket.Opcode.Dispatch,
|
||||||
|
Event: "READY",
|
||||||
|
Sequence: 1,
|
||||||
|
Data:
|
||||||
|
{
|
||||||
|
User:
|
||||||
|
{
|
||||||
|
Id:1234,
|
||||||
|
Username: "abrakadabra",
|
||||||
|
Discriminator: "1111",
|
||||||
|
GlobalName: "glblname"
|
||||||
|
},
|
||||||
|
Version: 10,
|
||||||
|
SessionId: "abcd",
|
||||||
|
ResumeGatewayUrl: "dfgh",
|
||||||
|
Guilds:[
|
||||||
|
{
|
||||||
|
Id: 5678,
|
||||||
|
Unavailable: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
Application:
|
||||||
|
{
|
||||||
|
Id: 3333,
|
||||||
|
Flags: 5555
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChannelCreateDeserialize()
|
||||||
|
{
|
||||||
|
string src = """
|
||||||
|
{
|
||||||
|
"op":0,
|
||||||
|
"t":"CHANNEL_CREATE",
|
||||||
|
"s":1,
|
||||||
|
"d":{
|
||||||
|
"id": "922243411795390570",
|
||||||
|
"type": 2,
|
||||||
|
"guild_id": "5678",
|
||||||
|
"position": 3,
|
||||||
|
"name": "voice csennel",
|
||||||
|
"topic": "A very interesting topic",
|
||||||
|
"nsfw": true,
|
||||||
|
"last_message_id":"6969",
|
||||||
|
"bitrate":420,
|
||||||
|
"parent_id": "5555"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
var gateway_packet =
|
||||||
|
JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket);
|
||||||
|
|
||||||
|
Assert.IsType<ChannelCreatePacket>(gateway_packet);
|
||||||
|
|
||||||
|
Assert.True(gateway_packet is ChannelCreatePacket
|
||||||
|
{
|
||||||
|
Op: GatewayPacket.Opcode.Dispatch,
|
||||||
|
Event: "CHANNEL_CREATE",
|
||||||
|
Sequence: 1,
|
||||||
|
Data:
|
||||||
|
{
|
||||||
|
Id: 922243411795390570,
|
||||||
|
Name: "voice csennel",
|
||||||
|
GuildId: 5678,
|
||||||
|
Type: 2,
|
||||||
|
Position: 3,
|
||||||
|
Topic: "A very interesting topic",
|
||||||
|
Nsfw: true,
|
||||||
|
Bitrate: 420,
|
||||||
|
ParentId: 5555,
|
||||||
|
LastMessageId: 6969
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,7 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_CREATE")]
|
internal class ChannelCreatePacket : DispatchPacket
|
||||||
public class ChannelCreatePacket : DispatchPacket
|
|
||||||
{
|
{
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonPropertyName("d")]
|
[JsonPropertyName("d")]
|
||||||
|
|||||||
@ -3,8 +3,7 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_DELETE")]
|
internal class ChannelDeletePacket : DispatchPacket
|
||||||
public class ChannelDeletePacket : DispatchPacket
|
|
||||||
{
|
{
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonPropertyName("d")]
|
[JsonPropertyName("d")]
|
||||||
|
|||||||
@ -3,8 +3,7 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_UPDATE")]
|
internal class ChannelUpdatePacket : DispatchPacket
|
||||||
public class ChannelUpdatePacket : DispatchPacket
|
|
||||||
{
|
{
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonPropertyName("d")]
|
[JsonPropertyName("d")]
|
||||||
|
|||||||
@ -3,9 +3,12 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonDerivedType(typeof(GatewayPacket), (int)Opcode.Dispatch)]
|
|
||||||
[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = true, TypeDiscriminatorPropertyName = "t", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = true, TypeDiscriminatorPropertyName = "t", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
||||||
public class DispatchPacket : GatewayPacket
|
[JsonDerivedType(typeof(ChannelCreatePacket))]
|
||||||
|
[JsonDerivedType(typeof(ChannelUpdatePacket))]
|
||||||
|
[JsonDerivedType(typeof(ChannelDeletePacket))]
|
||||||
|
[JsonDerivedType(typeof(ReadyPacket))]
|
||||||
|
internal class DispatchPacket : GatewayPacket
|
||||||
{
|
{
|
||||||
[JsonPropertyName("t")]
|
[JsonPropertyName("t")]
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
|
|||||||
@ -3,8 +3,9 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonDerivedType(typeof(DispatchPacket), "READY")]
|
[JsonPolymorphic(TypeDiscriminatorPropertyName = "t", IgnoreUnrecognizedTypeDiscriminators = true, UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
||||||
public class ReadyPacket : DispatchPacket
|
[JsonDerivedType(typeof(ReadyPacket))]
|
||||||
|
internal class ReadyPacket : DispatchPacket
|
||||||
{
|
{
|
||||||
public sealed class ReadyData
|
public sealed class ReadyData
|
||||||
{
|
{
|
||||||
@ -15,13 +16,13 @@ public class ReadyPacket : DispatchPacket
|
|||||||
public UserData User;
|
public UserData User;
|
||||||
|
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
public UnavailableGuildData Guilds;
|
public UnavailableGuildData[] Guilds;
|
||||||
|
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
public string SessionId;
|
public string SessionId;
|
||||||
|
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
public string ResumeUrl;
|
public string ResumeGatewayUrl;
|
||||||
|
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
public PartialApplicationData Application;
|
public PartialApplicationData Application;
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = false, TypeDiscriminatorPropertyName = "op", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = true, TypeDiscriminatorPropertyName = "op", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
||||||
public class GatewayPacket
|
[JsonDerivedType(typeof(IdentifyPacket))]
|
||||||
|
[JsonDerivedType(typeof(DispatchPacket))]
|
||||||
|
internal class GatewayPacket
|
||||||
{
|
{
|
||||||
public enum Opcode
|
public enum Opcode
|
||||||
{
|
{
|
||||||
|
|||||||
72
Discord.API/GatewayPacketTypes/GatewayPacketConverter.cs
Normal file
72
Discord.API/GatewayPacketTypes/GatewayPacketConverter.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
internal class GatewayPacketConverter : JsonConverter<GatewayPacket>
|
||||||
|
{
|
||||||
|
public override GatewayPacket? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
JsonDocument json_doc = JsonDocument.ParseValue(ref reader);
|
||||||
|
if(json_doc.RootElement.TryGetProperty("op", out JsonElement opcode_element))
|
||||||
|
{
|
||||||
|
if (opcode_element.ValueKind != JsonValueKind.Number)
|
||||||
|
{
|
||||||
|
throw new JsonException("Opcode is not a number");
|
||||||
|
}
|
||||||
|
|
||||||
|
GatewayPacket.Opcode op = (GatewayPacket.Opcode)opcode_element.GetInt32();
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case GatewayPacket.Opcode.Dispatch:
|
||||||
|
if (json_doc.RootElement.TryGetProperty("t", out JsonElement event_element))
|
||||||
|
{
|
||||||
|
if (event_element.ValueKind != JsonValueKind.String)
|
||||||
|
{
|
||||||
|
throw new Exception("Event name not string");
|
||||||
|
}
|
||||||
|
|
||||||
|
string? event_name = event_element.GetString();
|
||||||
|
switch (event_name)
|
||||||
|
{
|
||||||
|
case "READY":
|
||||||
|
return json_doc.Deserialize(SourceGenerationContext.Default.ReadyPacket);
|
||||||
|
case "CHANNEL_CREATE":
|
||||||
|
return json_doc.Deserialize(SourceGenerationContext.Default
|
||||||
|
.ChannelCreatePacket);
|
||||||
|
case "CHANNEL_UPDATE":
|
||||||
|
return json_doc.Deserialize(SourceGenerationContext.Default.ChannelUpdatePacket);
|
||||||
|
case "CHANNEL_DELETE":
|
||||||
|
return json_doc.Deserialize(SourceGenerationContext.Default.ChannelDeletePacket);
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"Packet {event_name} is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new JsonException("Event name not found");
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"Opcode {op} is not supported in json deserialization");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Opcode not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, GatewayPacket value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case IdentifyPacket id_packet:
|
||||||
|
writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(id_packet, SourceGenerationContext.Default.IdentifyPacket));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(value, SourceGenerationContext.Default.IdentifyPacket));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
//[JsonDerivedType(typeof(GatewayPacket), (int)Opcode.Identify)]
|
internal class IdentifyPacket : GatewayPacket
|
||||||
public class IdentifyPacket : GatewayPacket
|
|
||||||
{
|
{
|
||||||
public sealed class IdentifyData
|
public sealed class IdentifyData
|
||||||
{
|
{
|
||||||
@ -19,7 +19,7 @@ public class IdentifyPacket : GatewayPacket
|
|||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonPropertyName("token")]
|
[JsonPropertyName("token")]
|
||||||
public required string Token { get; set; }
|
public required string Token { get; init; }
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public PropertiesClass Properties => PropertiesClass.Instance;
|
public PropertiesClass Properties => PropertiesClass.Instance;
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
@ -27,10 +27,10 @@ public class IdentifyPacket : GatewayPacket
|
|||||||
public int LargeThreshold = 250;
|
public int LargeThreshold = 250;
|
||||||
public int[]? Shard = null;
|
public int[]? Shard = null;
|
||||||
//presence
|
//presence
|
||||||
public ulong Intents { get; init; }
|
public required ulong Intents { get; init; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonPropertyName("d")]
|
[JsonPropertyName("d")]
|
||||||
public IdentifyData Data;
|
public required IdentifyData Data { get; init; }
|
||||||
}
|
}
|
||||||
3
Discord.API/InternalsVisible.cs
Normal file
3
Discord.API/InternalsVisible.cs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly:InternalsVisibleTo("Discord.API.Tests")]
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.InteropServices.JavaScript;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Text.Json.Serialization.Metadata;
|
using System.Text.Json.Serialization.Metadata;
|
||||||
|
|
||||||
@ -5,9 +6,20 @@ namespace Discord.API;
|
|||||||
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
[JsonSourceGenerationOptions(IgnoreReadOnlyFields = false, IgnoreReadOnlyProperties = false, IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)]
|
[JsonSourceGenerationOptions(IgnoreReadOnlyFields = false,
|
||||||
|
IgnoreReadOnlyProperties = false,
|
||||||
|
IncludeFields = true,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower,
|
||||||
|
Converters = [typeof(GatewayPacketConverter)],
|
||||||
|
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||||
|
)]
|
||||||
[JsonSerializable(typeof(GatewayPacket))]
|
[JsonSerializable(typeof(GatewayPacket))]
|
||||||
[JsonSerializable(typeof(IdentifyPacket))]
|
[JsonSerializable(typeof(IdentifyPacket))]
|
||||||
|
[JsonSerializable(typeof(ChannelCreatePacket))]
|
||||||
|
[JsonSerializable(typeof(ChannelUpdatePacket))]
|
||||||
|
[JsonSerializable(typeof(ChannelDeletePacket))]
|
||||||
|
[JsonSerializable(typeof(DispatchPacket))]
|
||||||
|
[JsonSerializable(typeof(ReadyPacket))]
|
||||||
internal partial class SourceGenerationContext : JsonSerializerContext
|
internal partial class SourceGenerationContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.API", "Discord.API\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example_bot", "example_bot\example_bot.csproj", "{331F5928-8E65-4782-8311-BC1E80F1C002}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example_bot", "example_bot\example_bot.csproj", "{331F5928-8E65-4782-8311-BC1E80F1C002}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.API.Tests", "Discord.API.Tests\Discord.API.Tests.csproj", "{E89333A2-11C4-4CFF-9F45-32D951E871CA}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -30,5 +32,9 @@ Global
|
|||||||
{331F5928-8E65-4782-8311-BC1E80F1C002}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{331F5928-8E65-4782-8311-BC1E80F1C002}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.Build.0 = Release|Any CPU
|
{331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E89333A2-11C4-4CFF-9F45-32D951E871CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E89333A2-11C4-4CFF-9F45-32D951E871CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E89333A2-11C4-4CFF-9F45-32D951E871CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E89333A2-11C4-4CFF-9F45-32D951E871CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user