diff --git a/Esiur.sln b/Esiur.sln index ac5e84a..e538933 100644 --- a/Esiur.sln +++ b/Esiur.sln @@ -105,6 +105,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.NodeFanoutSweep EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.NodeFanoutSweep.Server", "Tests\Distribution\NodeFanoutSweep\Server\Esiur.Tests.NodeFanoutSweep.Server.csproj", "{9FF626DF-1AD4-2BE1-F834-F49121D65085}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RPC", "RPC", "{2023D47B-18D1-45F1-B7D2-CF53E868DA46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.Client", "Tests\RPC\Client\Esiur.Tests.RPC.Client.csproj", "{BBA981D1-17EE-6A4A-F4B2-CD89526D498A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.EsiurServer", "Tests\RPC\Esiur\Esiur.Tests.RPC.EsiurServer.csproj", "{24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.GrpcServer", "Tests\RPC\gRPC\Esiur.Tests.RPC.GrpcServer.csproj", "{04FFD019-027D-3306-CA69-8C7390717B87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.JsonServer", "Tests\RPC\Json\Esiur.Tests.RPC.JsonServer.csproj", "{46ED42EA-E808-AEF4-4306-22368535580D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.SignalRServer", "Tests\RPC\SignalR\Esiur.Tests.RPC.SignalRServer.csproj", "{3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Tests.RPC.ThriftServer", "Tests\RPC\Thrift\Esiur.Tests.RPC.ThriftServer.csproj", "{7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -403,6 +417,78 @@ Global {9FF626DF-1AD4-2BE1-F834-F49121D65085}.Release|x64.Build.0 = Release|Any CPU {9FF626DF-1AD4-2BE1-F834-F49121D65085}.Release|x86.ActiveCfg = Release|Any CPU {9FF626DF-1AD4-2BE1-F834-F49121D65085}.Release|x86.Build.0 = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|x64.ActiveCfg = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|x64.Build.0 = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|x86.ActiveCfg = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Debug|x86.Build.0 = Debug|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|Any CPU.Build.0 = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|x64.ActiveCfg = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|x64.Build.0 = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|x86.ActiveCfg = Release|Any CPU + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A}.Release|x86.Build.0 = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|x64.Build.0 = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Debug|x86.Build.0 = Debug|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|Any CPU.Build.0 = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|x64.ActiveCfg = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|x64.Build.0 = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|x86.ActiveCfg = Release|Any CPU + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC}.Release|x86.Build.0 = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|x64.ActiveCfg = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|x64.Build.0 = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|x86.ActiveCfg = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Debug|x86.Build.0 = Debug|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|Any CPU.Build.0 = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|x64.ActiveCfg = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|x64.Build.0 = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|x86.ActiveCfg = Release|Any CPU + {04FFD019-027D-3306-CA69-8C7390717B87}.Release|x86.Build.0 = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|x64.ActiveCfg = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|x64.Build.0 = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|x86.ActiveCfg = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Debug|x86.Build.0 = Debug|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|Any CPU.Build.0 = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|x64.ActiveCfg = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|x64.Build.0 = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|x86.ActiveCfg = Release|Any CPU + {46ED42EA-E808-AEF4-4306-22368535580D}.Release|x86.Build.0 = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|x64.ActiveCfg = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|x64.Build.0 = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|x86.ActiveCfg = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Debug|x86.Build.0 = Debug|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|Any CPU.Build.0 = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|x64.ActiveCfg = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|x64.Build.0 = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|x86.ActiveCfg = Release|Any CPU + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD}.Release|x86.Build.0 = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|x64.ActiveCfg = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|x64.Build.0 = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|x86.ActiveCfg = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Debug|x86.Build.0 = Debug|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|Any CPU.Build.0 = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|x64.ActiveCfg = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|x64.Build.0 = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|x86.ActiveCfg = Release|Any CPU + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -453,6 +539,13 @@ Global {F2FE7C0B-58C1-D768-C37A-D428D2B85940} = {967F62B4-2815-473F-9F1E-E7F146EE8872} {550A20AB-8E97-BCDD-9F54-27823663120A} = {21D42B96-99F9-4E48-A499-5170A5A9597F} {9FF626DF-1AD4-2BE1-F834-F49121D65085} = {57E80693-7AFC-4446-87DE-25E97C036E2F} + {2023D47B-18D1-45F1-B7D2-CF53E868DA46} = {2769C4C3-2595-413B-B7FE-5903826770C1} + {BBA981D1-17EE-6A4A-F4B2-CD89526D498A} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} + {24C2AA1F-2A3E-319C-4D1A-0D3CA34282DC} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} + {04FFD019-027D-3306-CA69-8C7390717B87} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} + {46ED42EA-E808-AEF4-4306-22368535580D} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} + {3CE2924C-1ED1-1949-D654-B8DCABBDF6FD} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} + {7ADA729C-6E99-B3D1-B16F-1D3DEEF11242} = {2023D47B-18D1-45F1-B7D2-CF53E868DA46} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C584421D-5EC0-4821-B7D8-2633D8D405F2} diff --git a/Libraries/Esiur/Data/TruTypeDef.cs b/Libraries/Esiur/Data/TruTypeDef.cs index d10bfaf..f544b03 100644 --- a/Libraries/Esiur/Data/TruTypeDef.cs +++ b/Libraries/Esiur/Data/TruTypeDef.cs @@ -1,5 +1,6 @@ using Esiur.Data.Types; using Esiur.Protocol; +using Esiur.Resource; using System; using System.Collections.Generic; using System.Text; @@ -28,9 +29,10 @@ namespace Esiur.Data TypeDef = typeDef; if (typeDef is LocalTypeDef localTypeDef) - RuntimeType = localTypeDef.DefinedType; + RuntimeType = localTypeDef.DefinedType ?? typeof(EpResource); else if (typeDef is RemoteTypeDef remoteTypeDef) - RuntimeType = remoteTypeDef.ProxyType; + RuntimeType = remoteTypeDef.ProxyType ?? typeof(IResource); + } public override void SetNull(byte flag) diff --git a/Libraries/Esiur/Protocol/EpConnection.cs b/Libraries/Esiur/Protocol/EpConnection.cs index d9c4438..b6d5300 100644 --- a/Libraries/Esiur/Protocol/EpConnection.cs +++ b/Libraries/Esiur/Protocol/EpConnection.cs @@ -1831,18 +1831,21 @@ public partial class EpConnection : NetworkConnection, IStore // assign domain from hostname if not provided if (context is EpConnectionContext epContext) { - var provider = Instance.Warehouse.GetAuthenticationProvider(epContext.AuthenticationProtocol); + var provider = Instance.Warehouse.TryGetAuthenticationProvider(epContext.AuthenticationProtocol); _remoteDomain = epContext.Domain ?? address; - _session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext() + if (provider != null) { - Direction = AuthenticationDirection.Initiator, - Domain = _remoteDomain, - HostName = address, - InitiatorIdentity = epContext.Identity, - Mode = epContext.AuthenticationMode, - }); + _session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext() + { + Direction = AuthenticationDirection.Initiator, + Domain = _remoteDomain, + HostName = address, + InitiatorIdentity = epContext.Identity, + Mode = epContext.AuthenticationMode, + }); + } _session.AuthenticationMode = epContext.AuthenticationMode; _session.LocalIdentity = epContext.Identity; diff --git a/Libraries/Esiur/Protocol/EpConnectionProtocol.cs b/Libraries/Esiur/Protocol/EpConnectionProtocol.cs index 3ca1264..5062817 100644 --- a/Libraries/Esiur/Protocol/EpConnectionProtocol.cs +++ b/Libraries/Esiur/Protocol/EpConnectionProtocol.cs @@ -2035,30 +2035,32 @@ partial class EpConnection public AsyncReply GetLinkDefinitions(string link) { - throw new NotImplementedException(); + //throw new NotImplementedException(); - //var reply = new AsyncReply(); + var reply = new AsyncReply(); - //SendRequest(EpPacketRequest.LinkTypeDefs, link) - //.Then((result) => - //{ + SendRequest(EpPacketRequest.LinkTypeDefs, link) + .Then(async (result) => + { - // var defs = new List(); + var defs = new List(); - // foreach (var def in (byte[][])result) - // { - // defs.Add(RemoteTypeDef.Parse(_remoteDomain, def)); - // } + foreach (var def in (byte[][])result) + { + var od = new RemoteTypeDef(); + await RemoteTypeDef.Parse(od, _remoteDomain, def, this, null); + defs.Add(od); + } - // reply.Trigger(defs.ToArray()); + reply.Trigger(defs.ToArray()); - //}).Error((ex) => - //{ - // reply.TriggerError(ex); - //}); + }).Error((ex) => + { + reply.TriggerError(ex); + }); - //return reply; + return reply; } /// diff --git a/Libraries/Esiur/Proxy/TypeDefGenerator.cs b/Libraries/Esiur/Proxy/TypeDefGenerator.cs index baf2f9a..4be5c8a 100644 --- a/Libraries/Esiur/Proxy/TypeDefGenerator.cs +++ b/Libraries/Esiur/Proxy/TypeDefGenerator.cs @@ -220,6 +220,7 @@ public static class TypeDefGenerator var path = urlRegex.Split(url); var con = Warehouse.Default.Get(path[1] + "://" + path[2], new EpConnectionContext() { + AuthenticationMode = Security.Authority.AuthenticationMode.None, Identity = username }).Wait(10000); diff --git a/Libraries/Esiur/Resource/Warehouse.cs b/Libraries/Esiur/Resource/Warehouse.cs index 2d2ff38..7361453 100644 --- a/Libraries/Esiur/Resource/Warehouse.cs +++ b/Libraries/Esiur/Resource/Warehouse.cs @@ -128,6 +128,15 @@ public class Warehouse throw new Exception("Authentication provider not found."); } + public IAuthenticationProvider? TryGetAuthenticationProvider(string name) + { + if (_authenticationProviders.ContainsKey(name)) + return _authenticationProviders[name]; + + return null; + } + + public Warehouse() { Protocols.Add("EP", diff --git a/Tests/RPC/Client/Esiur.Tests.RPC.Client.csproj b/Tests/RPC/Client/Esiur.Tests.RPC.Client.csproj new file mode 100644 index 0000000..90e812d --- /dev/null +++ b/Tests/RPC/Client/Esiur.Tests.RPC.Client.csproj @@ -0,0 +1,40 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/RPC/Client/Model/Esiur/Esiur.Generated.cs b/Tests/RPC/Client/Model/Esiur/Esiur.Generated.cs new file mode 100644 index 0000000..80bb5bc --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/Esiur.Generated.cs @@ -0,0 +1,10 @@ +using System; +namespace Esiur +{ + public static class Generated + { + public static Type[] Resources { get; } = new Type[] { typeof(RPC.EsiurTest.Service), typeof(RPC.EsiurTest.TestObject) }; + public static Type[] Records { get; } = new Type[] { typeof(RPC.EsiurTest.BusinessDocument), typeof(RPC.EsiurTest.Attachment), typeof(RPC.EsiurTest.Party), typeof(RPC.EsiurTest.Address), typeof(RPC.EsiurTest.DocumentHeader), typeof(RPC.EsiurTest.LineItem), typeof(RPC.EsiurTest.Variant), typeof(RPC.EsiurTest.Payment) }; + public static Type[] Enums { get; } = new Type[] { typeof(RPC.EsiurTest.Currency), typeof(RPC.EsiurTest.DocType), typeof(RPC.EsiurTest.Kind), typeof(RPC.EsiurTest.LineType), typeof(RPC.EsiurTest.PaymentMethod) }; + } +} \ No newline at end of file diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Address.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Address.Generated.cs new file mode 100644 index 0000000..943a087 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Address.Generated.cs @@ -0,0 +1,84 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("0f8f447ee993847189b2c1ad6f83931a")] + [Export] + public class Address : IRecord + { + [Annotation("String")] + public string City { get; set; } + + [Annotation("String")] + public string Country { get; set; } + + [Annotation("String")] + public string Line1 { get; set; } + + [Annotation("String")] + public string? Line2 { get; set; } + + [Annotation("String")] + public string? PostalCode { get; set; } + + [Annotation("String")] + public string Region { get; set; } + + public override bool Equals(object? obj) + { + var other = obj as Address; + if (other == null) return false; + if (other.Line1 != Line1) return false; + if (other.Line2 != Line2) return false; + if (other.PostalCode != PostalCode) return false; + if (other.City != City) return false; + if (other.Country != Country) return false; + if (other.Region != Region) return false; + + return true; + } + + public SharedModel.Address ToShared() + { + return new SharedModel.Address() + { + City = City, + Country = Country, + Line1 = Line1, + Line2 = Line2, + PostalCode = PostalCode, + Region = Region, + + }; + } + + public Echo.Model.Grpc.Address ToGrpc() + { + return new Echo.Model.Grpc.Address() + { + City = City, + Country = Country, + Line1 = Line1, + Line2 = Line2 ?? "", + PostalCode = PostalCode ?? "", + Region = Region, + }; + } + + public Echo.ThriftModel.Address ToThrift() + { + return new Echo.ThriftModel.Address() + { + City = City, + Country = Country, + Line1 = Line1, + Line2 = Line2, + PostalCode = PostalCode, + Region = Region, + }; + } + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Attachment.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Attachment.Generated.cs new file mode 100644 index 0000000..581c377 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Attachment.Generated.cs @@ -0,0 +1,62 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +using Google.Protobuf; +namespace RPC.EsiurTest +{ + [TypeId("4befaa686f038a2885268fca4cbf3c2c")] + [Export] + public class Attachment : IRecord + { + [Annotation("Byte[]")] + public byte[] Data { get; set; } + + [Annotation("String")] + public string MimeType { get; set; } + + [Annotation("String")] + public string Name { get; set; } + + public override bool Equals(object? obj) + { + var other = obj as Attachment; + if (Name != other.Name) return false; + if (MimeType != other.MimeType) return false; + if (!(Data.SequenceEqual(other.Data))) return false; + + return true; + } + + public SharedModel.Attachment ToShared() + { + return new SharedModel.Attachment() + { + Data = Data, + MimeType = MimeType, + Name = Name, + }; + } + + public Echo.Model.Grpc.Attachment ToGrpc() + { + return new Echo.Model.Grpc.Attachment() + { + Data = ByteString.CopyFrom(Data), + MimeType = MimeType, + Name = Name, + }; + } + + public Echo.ThriftModel.Attachment ToThrift() + { + return new Echo.ThriftModel.Attachment() + { + Data = Data, + MimeType = MimeType, + Name = Name, + }; + } + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.BusinessDocument.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.BusinessDocument.Generated.cs new file mode 100644 index 0000000..c2a01e4 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.BusinessDocument.Generated.cs @@ -0,0 +1,145 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +using Google.Protobuf; +using Google.Protobuf.Collections; +namespace RPC.EsiurTest +{ + [TypeId("9a34d22890e787b48133a2a61ac84ad8")] + [Export] + public class BusinessDocument : IRecord + { + [Annotation("Attachment[]")] + public RPC.EsiurTest.Attachment[] Attachments { get; set; } + + [Annotation("Party")] + public RPC.EsiurTest.Party Buyer { get; set; } + + [Annotation("DocumentHeader")] + public RPC.EsiurTest.DocumentHeader Header { get; set; } + + [Annotation("LineItem[]")] + public RPC.EsiurTest.LineItem[] Items { get; set; } + + [Annotation("Payment[]")] + public RPC.EsiurTest.Payment[] Payments { get; set; } + + [Annotation("Int32[]")] + public int[] RiskScores { get; set; } + + [Annotation("Party")] + public RPC.EsiurTest.Party Seller { get; set; } + + public override bool Equals(object? obj) + { + var other = obj as BusinessDocument; + if (other == null) + return false; + + + if (!Header.Equals(other.Header)) + return false; + if (!Seller.Equals(other.Seller)) + return false; + if (!Buyer.Equals(other.Buyer)) + return false; + + if (Items != null) + for (var i = 0; i < Items.Length; i++) + if (!Items[i].Equals(other.Items[i])) + return false; + + if (Payments != null) + for (var i = 0; i < Payments.Length; i++) + if (!Payments[i].Equals(other.Payments[i])) + return false; + + if (Attachments != null) + for (var i = 0; i < Attachments.Length; i++) + if (!Attachments[i].Equals(other.Attachments[i])) + return false; + + if (!RiskScores.SequenceEqual(other.RiskScores)) + return false; + + return true; + } + + + public SharedModel.BusinessDocument ToShared() + { + return new SharedModel.BusinessDocument() + { + Attachments = Attachments?.Select(x=>x.ToShared()).ToArray() ?? null, + Buyer = Buyer.ToShared(), + Header = Header.ToShared(), + Items = Items.Select(x=>x.ToShared()).ToArray(), + Payments = Payments.Select(x=>x.ToShared()).ToArray(), + RiskScores = RiskScores, + Seller = Seller.ToShared(), + }; + } + + public Echo.ThriftModel.BusinessDocument ToThrift() + { + var rt = new Echo.ThriftModel.BusinessDocument(); + + if (Header != null) + rt.Header = Header.ToThrift(); + + if (Buyer != null) + rt.Buyer = Buyer.ToThrift(); + + if (Seller != null) + rt.Seller = Seller.ToThrift(); + + if (Attachments != null) + rt.Attachments = Attachments.Select(x=>x.ToThrift()).ToList(); + + if (RiskScores != null) + rt.RiskScores = RiskScores.ToList(); + + if (Items != null) + rt.Items = Items.Select(x => x.ToThrift()).ToList(); + + if (Payments != null) + rt.Payments = Payments.Select(x => x.ToThrift()).ToList(); + + return rt; + } + + public Echo.Model.Grpc.BusinessDocument ToGrpc() + { + + var rt = new Echo.Model.Grpc.BusinessDocument() + { + Header = Header.ToGrpc(), + Buyer = Buyer.ToGrpc(), + Seller = Seller.ToGrpc(), + }; + + + if (Payments != null) + foreach (var p in Payments) + rt.Payments.Add(p.ToGrpc()); + + if (Attachments != null) + foreach (var p in Attachments) + rt.Attachments.Add(p.ToGrpc()); + + if (Items != null) + foreach (var p in Items) + rt.Items.Add(p.ToGrpc()); + + if (RiskScores != null) + foreach (var p in RiskScores) + rt.RiskScores.Add(p); + + return rt; + } + + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Currency.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Currency.Generated.cs new file mode 100644 index 0000000..56fb6d0 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Currency.Generated.cs @@ -0,0 +1,20 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("c44e42333dfd8d3485bb2a79fd7a9f6f")] + [Export] + public enum Currency + { + CNH = 1, + EUR = 3, + GBP = 5, + IQD = 0, + JPY = 4, + USD = 2 + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocType.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocType.Generated.cs new file mode 100644 index 0000000..06b1701 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocType.Generated.cs @@ -0,0 +1,18 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("6ded4eca74c8886a85a74e082770be4b")] + [Export] + public enum DocType + { + CreditNote = 3, + Invoice = 2, + Order = 1, + Quote = 0 + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocumentHeader.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocumentHeader.Generated.cs new file mode 100644 index 0000000..8fbbc1e --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.DocumentHeader.Generated.cs @@ -0,0 +1,114 @@ +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +using Esiur.Resource; +using Google.Protobuf; +using System; +namespace RPC.EsiurTest +{ + [TypeId("4631164f62d489e68ffab70e20b421f2")] + [Export] + public class DocumentHeader : IRecord + { + [Annotation("DateTime")] + public DateTime CreatedAt { get; set; } + + [Annotation("Currency")] + public RPC.EsiurTest.Currency Currency { get; set; } + + [Annotation("Byte[]")] + public byte[] DocId { get; set; } + + [Annotation("Dictionary`2")] + public Map Meta { get; set; } + + [Annotation("String")] + public string? Notes { get; set; } + + [Annotation("DocType")] + public RPC.EsiurTest.DocType Type { get; set; } + + [Annotation("Nullable`1?")] + public DateTime? UpdatedAt { get; set; } + + [Annotation("Int32")] + public int Version { get; set; } + + + public SharedModel.DocumentHeader ToShared() + { + return new SharedModel.DocumentHeader() + { + CreatedAt = CreatedAt, + DocId = DocId, + Meta = Meta.ToDictionary(x=>x.Key, v=>v.Value.ToShared()), + Notes = Notes, + Currency = Enum.Parse(Currency.ToString(), true), + UpdatedAt = UpdatedAt, + Version = Version, + Type = Enum.Parse(Type.ToString(), true) + }; + } + + public Echo.ThriftModel.DocumentHeader ToThrift() + { + var rt = new Echo.ThriftModel.DocumentHeader() + { + DocId = DocId, + CreatedAt = CreatedAt.Ticks, + Currency = Enum.Parse< Echo.ThriftModel.Currency>(Currency.ToString(), true), + Type = Enum.Parse< Echo.ThriftModel.DocType>(Type.ToString(), true), + Version = Version, + Meta = Meta.ToDictionary(x=>x.Key, x=>x.Value.ToThrift()) + }; + + if (UpdatedAt != null) + rt.UpdatedAt = UpdatedAt.Value.Ticks; + + if (Notes != null) + rt.Notes = Notes; + + return rt; + } + + public Echo.Model.Grpc.DocumentHeader ToGrpc() + { + var hdr = new Echo.Model.Grpc.DocumentHeader(); + + hdr.DocId = ByteString.CopyFrom(DocId); + hdr.CreatedAt = CreatedAt.Ticks; + hdr.Currency = Enum.Parse(Currency.ToString(), true); + hdr.Version = Version; + hdr.Notes = Notes; + + foreach (var mt in Meta) + hdr.Meta.Add(mt.Key, mt.Value.ToGrpc()); + + return hdr; + } + + public override bool Equals(object? obj) + { + var other = obj as DocumentHeader; + + if (other == null) return false; + if (!DocId.SequenceEqual(other.DocId)) return false; + if (Type != other.Type) return false; + if (Version != other.Version) return false; + + if (CreatedAt != other.CreatedAt) return false; + if (UpdatedAt != other.UpdatedAt) return false; + + if (Currency != other.Currency) return false; + if (Notes != other.Notes) return false; + + if (Meta != null) + foreach (var kv in Meta) + if (!other.Meta[kv.Key].Equals(kv.Value)) + return false; + + return true; + } + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Kind.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Kind.Generated.cs new file mode 100644 index 0000000..4f6b599 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Kind.Generated.cs @@ -0,0 +1,24 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("32ae8265068382608399b7e427be37db")] + [Export] + public enum Kind + { + Bool = 1, + Bytes = 7, + DateTime = 8, + Decimal = 5, + Double = 4, + Guid = 9, + Int64 = 2, + Null = 0, + String = 6, + UInt64 = 3 + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineItem.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineItem.Generated.cs new file mode 100644 index 0000000..92e78da --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineItem.Generated.cs @@ -0,0 +1,132 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("142f42b0e1a78c098f35fa935cde22c1")] + [Export] + public class LineItem : IRecord + { + [Annotation("String")] + public string Description { get; set; } + + [Annotation("Nullable`1?")] + public double? Discount { get; set; } + + [Annotation("Map`2")] + public Map Ext { get; set; } + + [Annotation("Int32")] + public int LineNo { get; set; } + + [Annotation("Double")] + public double Qty { get; set; } + + [Annotation("String")] + public string QtyUnit { get; set; } + + [Annotation("String")] + public string SKU { get; set; } + + [Annotation("LineType")] + public RPC.EsiurTest.LineType Type { get; set; } + + [Annotation("Double")] + public double UnitPrice { get; set; } + + [Annotation("Nullable`1?")] + public double? VatRate { get; set; } + + + public SharedModel.LineItem ToShared() + { + return new SharedModel.LineItem() + { + Description = Description, + Discount = Discount, + Ext = Ext.ToDictionary(k => k.Key, v => v.Value.ToShared()), + LineNo = LineNo, + Qty = Qty, + QtyUnit = QtyUnit, + SKU = SKU, + Type = Enum.Parse(Type.ToString(), true), + UnitPrice = UnitPrice, + VatRate = VatRate + }; + } + public Echo.ThriftModel.LineItem ToThrift() + { + var rt = new Echo.ThriftModel.LineItem() + { + Description = Description, + LineNo = LineNo, + Qty = Qty, + UnitPrice = UnitPrice, + QtyUnit = QtyUnit, + Sku = SKU, + Type = Enum.Parse(Type.ToString(), true), + }; + + if (Discount != null) + rt.Discount = Discount.Value; + if (VatRate != null) + rt.VatRate = VatRate.Value; + + if (Ext != null) + rt.Ext = Ext.ToDictionary(x => x.Key, v => v.Value.ToThrift()); + + return rt; + } + + public Echo.Model.Grpc.LineItem ToGrpc() + { + var rt = new Echo.Model.Grpc.LineItem() + { + Description = Description, + Discount = Discount ?? 0, + LineNo = LineNo, + Qty = Qty, + UnitPrice = UnitPrice, + QtyUnit = QtyUnit, + Sku = SKU, + Type = Enum.Parse(Type.ToString(), true), + VatRate = VatRate ?? 0, + }; + + if (Ext != null) + { + foreach (var kv in Ext) + rt.Ext.Add(kv.Key, kv.Value.ToGrpc()); + } + + return rt; + } + + public override bool Equals(object? obj) + { + var other = obj as LineItem; + if (other == null) return false; + if (other.LineNo != LineNo) return false; + if (other.SKU != SKU) return false; + if (other.Description != Description) return false; + if (other.Discount != Discount) return false; + if (other.QtyUnit != QtyUnit) return false; + if (other.Type != Type) return false; + if (other.VatRate != VatRate) return false; + if (other.UnitPrice != UnitPrice) return false; + + + if (Ext != null) + { + foreach (var kv in Ext) + if (!other.Ext[kv.Key].Equals(kv.Value)) + return false; + } + + return true; + } + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineType.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineType.Generated.cs new file mode 100644 index 0000000..0017fff --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.LineType.Generated.cs @@ -0,0 +1,18 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("7e474e8826e288f28bddddf69782c580")] + [Export] + public enum LineType + { + Discount = 2, + Product = 0, + Service = 1, + Shipping = 3 + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Party.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Party.Generated.cs new file mode 100644 index 0000000..9728e83 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Party.Generated.cs @@ -0,0 +1,93 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("44fff9c7bd9b86f580bf479a64cb84af")] + [Export] + public class Party : IRecord + { + [Annotation("Address")] + public RPC.EsiurTest.Address Address { get; set; } + + [Annotation("String")] + public string Email { get; set; } + + [Annotation("UInt64")] + public ulong Id { get; set; } + + [Annotation("String")] + public string Name { get; set; } + + [Annotation("String")] + public string Phone { get; set; } + + [Annotation("String")] + public string PreferredLanguage { get; set; } + + [Annotation("String")] + public string TaxId { get; set; } + + public SharedModel.Party ToShared() + { + return new SharedModel.Party() + { + Address = Address.ToShared(), + Email = Email, + Id = Id, + Name = Name, + Phone = Phone, + PreferredLanguage = PreferredLanguage, + TaxId = TaxId, + }; + } + + public Echo.ThriftModel.Party ToThrift() + { + return new Echo.ThriftModel.Party() + { + Address = Address.ToThrift(), + Email = Email, + Id = (long)Id, + Name = Name, + Phone = Phone, + PreferredLanguage = PreferredLanguage, + TaxId = TaxId + }; + } + + public Echo.Model.Grpc.Party ToGrpc() + { + return new Echo.Model.Grpc.Party() + { + Address = Address.ToGrpc(), + Email = Email, + Id = Id, + Name = Name, + Phone = Phone, + PreferredLanguage = PreferredLanguage ?? "", + TaxId = TaxId ?? "", + }; + } + + public override bool Equals(object? obj) + { + var other = obj as Party; + if (other == null) return false; + + if (other.Id != Id) return false; + + if (other.TaxId != TaxId) return false; + if (!other.Address.Equals(Address)) return false; + if (other.Email != Email) return false; + if (other.Name != Name) return false; + if (other.Phone != Phone) return false; + if (other.PreferredLanguage != PreferredLanguage) return false; + + return true; + } + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Payment.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Payment.Generated.cs new file mode 100644 index 0000000..e7bbdf8 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Payment.Generated.cs @@ -0,0 +1,87 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("f172196340298b8586fed434c72bc158")] + [Export] + public class Payment : IRecord + { + [Annotation("Double")] + public double Amount { get; set; } + + [Annotation("Currency")] + public RPC.EsiurTest.Currency Currency { get; set; } + + [Annotation("Nullable`1?")] + public double? Fee { get; set; } + + [Annotation("PaymentMethod")] + public RPC.EsiurTest.PaymentMethod Method { get; set; } + + [Annotation("String")] + public string Reference { get; set; } + + [Annotation("DateTime")] + public DateTime Timestamp { get; set; } + + + public SharedModel.Payment ToShared() + { + return new SharedModel.Payment() + { + Amount = Amount, + Currency = Enum.Parse(Currency.ToString(), true), + Method = Enum.Parse(Method.ToString(), true), + Reference = Reference, + Timestamp = Timestamp, + Fee = Fee, + }; + } + + public Echo.ThriftModel.Payment ToThrift() + { + var rt= new Echo.ThriftModel.Payment() + { + Amount = Amount, + Currency = Enum.Parse(Currency.ToString(), true), + Method = Enum.Parse(Method.ToString(), true), + Reference = Reference, + Timestamp = Timestamp.Ticks, + }; + + if (Fee != null) + rt.Fee = Fee.Value; + + return rt; + } + + public Echo.Model.Grpc.Payment ToGrpc() + { + return new Echo.Model.Grpc.Payment() + { + Amount = Amount, + Currency = Enum.Parse(Currency.ToString(), true), + Fee = Fee ?? 0, + Method = Enum.Parse(Method.ToString(), true), + Reference = Reference, + Timestamp = Timestamp.Ticks, + }; + } + public override bool Equals(object? obj) + { + var other = obj as Payment; + + if (other == null) return false; + + if (Method != other.Method) return false; + if (Amount != other.Amount) return false; + if (Reference != other.Reference) return false; + if (Fee != other.Fee) return false; + + return true; + } + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.PaymentMethod.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.PaymentMethod.Generated.cs new file mode 100644 index 0000000..807d54d --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.PaymentMethod.Generated.cs @@ -0,0 +1,19 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +namespace RPC.EsiurTest +{ + [TypeId("fadfe3764f808d7e839fef5275490dd7")] + [Export] + public enum PaymentMethod + { + Card = 1, + Cash = 0, + Crypto = 3, + Other = 4, + Wire = 2 + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Service.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Service.Generated.cs new file mode 100644 index 0000000..46f711a --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Service.Generated.cs @@ -0,0 +1,196 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +#nullable enable +namespace RPC.EsiurTest +{ + //{ab8e681b-61d9-8fb7-8c63-bbded15457e1} + [TypeId("f7e00be8881d88d68a8a2dc2d3a4b3d1")] + public class Service : EpResource + { + public Service(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { } + public Service() { } + [Annotation("([Int32] count,[Int32] size,[Int32] delay) -> AsyncReply`1")] + [Export] + public AsyncReply ChunkTest(int count, int size, int delay) + { + var args = new Map() { [0] = count, [1] = size, [2] = delay }; + var rt = new AsyncReply(); + _Invoke(0, args) + .Then(x => rt.Trigger((byte[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Byte[]] payload) -> Byte[]")] + [Export] + public AsyncReply EchoBytes(byte[] payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply(); + _Invoke(1, args) + .Then(x => rt.Trigger((byte[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([BusinessDocument[]] payload) -> BusinessDocument[]")] + [Export] + public AsyncReply EchoDocuments(RPC.EsiurTest.BusinessDocument[] payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply(); + _Invoke(2, args) + .Then(x => rt.Trigger((RPC.EsiurTest.BusinessDocument[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([DocType[]] payload) -> DocType[]")] + [Export] + public AsyncReply EchoEnumArray(RPC.EsiurTest.DocType[] payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply(); + _Invoke(3, args) + .Then(x => rt.Trigger((RPC.EsiurTest.DocType[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32[]] payload) -> Int32[]")] + [Export] + public AsyncReply EchoIntArray(int[] payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply(); + _Invoke(4, args) + .Then(x => rt.Trigger((int[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Map`2] payload) -> Map`2")] + [Export] + public AsyncReply> EchoMap(Map payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply>(); + _Invoke(5, args) + .Then(x => rt.Trigger((Map)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([String[]] payload) -> String[]")] + [Export] + public AsyncReply EchoStringArray(string[] payload) + { + var args = new Map() { [0] = payload }; + var rt = new AsyncReply(); + _Invoke(6, args) + .Then(x => rt.Trigger((string[])x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] count,[Int32] size,[Int32] delay) -> Void")] + [Export] + public AsyncReply EventTest(int count, int size, int delay) + { + var args = new Map() { [0] = count, [1] = size, [2] = delay }; + var rt = new AsyncReply(); + _Invoke(7, args) + .Then(x => rt.Trigger((object)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] count,[Int32] size,[Int32] delay) -> Void")] + [Export] + public AsyncReply PropertyChangeTest(int count, int size, int delay) + { + var args = new Map() { [0] = count, [1] = size, [2] = delay }; + var rt = new AsyncReply(); + _Invoke(8, args) + .Then(x => rt.Trigger((object)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] interval,[Int32] count,[Double] localProbability,[Double] remoteProbability,[String] remoteHostLink) -> AsyncReply`1")] + [Export] + public AsyncReply StartUpdates(int interval, int count, double localProbability, double remoteProbability, string remoteHostLink) + { + var args = new Map() { [0] = interval, [1] = count, [2] = localProbability, [3] = remoteProbability, [4] = remoteHostLink }; + var rt = new AsyncReply(); + _Invoke(9, args) + .Then(x => rt.Trigger((RPC.EsiurTest.TestObject)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] interval,[Int32] count,[Double] localProbability) -> AsyncReply`1")] + [Export] + public AsyncReply StartUpdatesLocal(int interval, int count, double localProbability) + { + var args = new Map() { [0] = interval, [1] = count, [2] = localProbability }; + var rt = new AsyncReply(); + _Invoke(10, args) + .Then(x => rt.Trigger((RPC.EsiurTest.TestObject)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] interval,[Int32] count,[Double] remoteProbability,[String] remoteNode,[String] remoteLink) -> AsyncReply`1")] + [Export] + public AsyncReply StartUpdatesMirror(int interval, int count, double remoteProbability, string remoteNode, string remoteLink) + { + var args = new Map() { [0] = interval, [1] = count, [2] = remoteProbability, [3] = remoteNode, [4] = remoteLink }; + var rt = new AsyncReply(); + _Invoke(11, args) + .Then(x => rt.Trigger((RPC.EsiurTest.TestObject)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("([Int32] interval,[Int32] count,[Double] remoteProbability,[String] remoteLink) -> AsyncReply`1")] + [Export] + public AsyncReply StartUpdatesRemote(int interval, int count, double remoteProbability, string remoteLink) + { + var args = new Map() { [0] = interval, [1] = count, [2] = remoteProbability, [3] = remoteLink }; + var rt = new AsyncReply(); + _Invoke(12, args) + .Then(x => rt.Trigger((RPC.EsiurTest.TestObject)x)) + .Error(x => rt.TriggerError(x)) + .Chunk(x => rt.TriggerChunk(x)); + return rt; + } + [Annotation("Byte[]")] + [Export] + public byte[] MessageToChange + { + get => (byte[])_properties[0]; + set => SetResourceProperty(0, value); + } + [Annotation("Object")] + [Export] + public object TestProperty + { + get => (object)_properties[1]; + set => SetResourceProperty(1, value); + } + protected override void _EmitEventByIndex(byte index, object args) + { + switch (index) + { + case 0: MessageUpdated?.Invoke((byte[])args); break; + } + } + [Export] public event ResourceEventHandler MessageUpdated; + + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Variant.Generated.cs b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Variant.Generated.cs new file mode 100644 index 0000000..0d2bd5c --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.Esiur.Variant.Generated.cs @@ -0,0 +1,121 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +using Google.Protobuf; + +namespace RPC.EsiurTest +{ + [TypeId("91ed22c5c53e846181f799dc76ddd93c")] + [Export] + public class Variant : IRecord + { + [Annotation("Nullable`1?")] + public bool? Bool { get; set; } + + [Annotation("Byte[]")] + public byte[] Bytes { get; set; } + + [Annotation("Nullable`1?")] + public DateTime? Dt { get; set; } + + [Annotation("Nullable`1?")] + public double? F64 { get; set; } + + [Annotation("Byte[]")] + public byte[] Guid { get; set; } + + [Annotation("Nullable`1?")] + public long? I64 { get; set; } + + [Annotation("String")] + public string Str { get; set; } + + [Annotation("Kind")] + public RPC.EsiurTest.Kind Tag { get; set; } + + [Annotation("Nullable`1?")] + public ulong? U64 { get; set; } + + public RPC.SharedModel.Variant ToShared() + { + return new SharedModel.Variant() + { + + Bool = Bool, + Bytes = Bytes, + Dt = Dt, + F64 = F64, + Guid = Guid, + I64 = I64, + Str = Str, + Tag = Enum.Parse(Tag.ToString(), true), + U64 = U64 + }; + } + + public Echo.Model.Grpc.Variant ToGrpc() + { + return new Echo.Model.Grpc.Variant() + { + BoolVal = Bool ?? false, + BytesVal = ByteString.CopyFrom(Bytes ?? new byte[0]), + DtVal = Dt?.Ticks ?? 0, + F64Val = F64 ?? 0, + GuidVal = ByteString.CopyFrom(Guid ?? new byte[0]), + I64Val = I64 ?? 0, + StrVal = Str, + Tag = Enum.Parse(Tag.ToString(), true), + U64Val = U64 ?? 0, + }; + } + + public Echo.ThriftModel.Variant ToThrift() + { + var rt = new Echo.ThriftModel.Variant() + { + Tag = Enum.Parse(Tag.ToString(), true), + }; + + if (Bool != null) + rt.BoolVal = Bool.Value; + if (Bytes != null) + rt.BytesVal = Bytes; + if (Dt != null) + rt.DtVal = Dt.Value.Ticks; + if (F64 != null) + rt.F64Val = F64.Value; + if (Guid != null) + rt.GuidVal = Guid; + if (I64 != null) + rt.I64Val = I64.Value; + return rt; + } + + public override bool Equals(object? obj) + { + var other = obj as Variant; + if (other == null) return false; + + if (other.I64 != I64) return false; + if (other.U64 != U64) return false; + if (other.Bool != Bool) return false; + //if (other.Dec != Dec) return false; + if (other.Str != Str) return false; + if (Guid != null) + if (!other.Guid.SequenceEqual(Guid)) return false; + if (other.F64 != F64) return false; + if (other.Tag != Tag) return false; + if (Bytes != null) + if (!other.Bytes.SequenceEqual(Bytes)) return false; + + if (other.Dt != Dt) + return false; + + return true; + } + + + } +} diff --git a/Tests/RPC/Client/Model/Esiur/RPC.EsiurTest.TestObject.g.cs b/Tests/RPC/Client/Model/Esiur/RPC.EsiurTest.TestObject.g.cs new file mode 100644 index 0000000..a6dce75 --- /dev/null +++ b/Tests/RPC/Client/Model/Esiur/RPC.EsiurTest.TestObject.g.cs @@ -0,0 +1,37 @@ +using System; +using Esiur.Resource; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +#nullable enable +namespace RPC.EsiurTest +{ + [TypeId("d90d3558e2b18d9a8f45707372ddf2c3")] + public class TestObject : EpResource + { + public TestObject(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { } + public TestObject() { } + [Annotation("String")] + [Export] + public string Name + { + get => (string)properties[0]; + set => SetResourceProperty(0, value); + } + [Annotation("Int32")] + [Export] + public int Size + { + get => (int)properties[1]; + set => SetResourceProperty(1, value); + } + [Annotation("Object")] + [Export] + public object Value + { + get => (object)properties[2]; + set => SetResourceProperty(2, value); + } + + } +} diff --git a/Tests/RPC/Client/Model/SharedModel.cs b/Tests/RPC/Client/Model/SharedModel.cs new file mode 100644 index 0000000..8ec1add --- /dev/null +++ b/Tests/RPC/Client/Model/SharedModel.cs @@ -0,0 +1,194 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace RPC.SharedModel +{ + // ====================== Enums ====================== + + public enum Currency + { + IQD, + CNH, + USD, + EUR, + JPY, + GBP + } + + public enum DocType + { + Quote, + Order, + Invoice, + CreditNote + } + + public enum PaymentMethod + { + Cash, + Card, + Wire, + Crypto, + Other + } + + public enum LineType + { + Product, + Service, + Discount, + Shipping + } + + // Variant.Kind + public enum Kind + { + Null, + Bool, + Int64, + UInt64, + Double, + Decimal, + String, + Bytes, + DateTime, + Guid + } + + // ====================== Variant & Entry helpers ====================== + + public sealed class Variant + { + public Kind Tag { get; set; } + + public bool? Bool { get; set; } + public long? I64 { get; set; } + public ulong? U64 { get; set; } + public double? F64 { get; set; } + public string? Str { get; set; } + public byte[]? Bytes { get; set; } + public DateTime? Dt { get; set; } + public byte[]? Guid { get; set; } + } + + public sealed class MetaEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + public sealed class ExtEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + // ====================== Party & Address ====================== + + public sealed class Address + { + public string Line1 { get; set; } = string.Empty; + public string? Line2 { get; set; } + + public string City { get; set; } = string.Empty; + public string Region { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string? PostalCode { get; set; } + } + + public sealed class Party + { + public ulong Id { get; set; } + + public string Name { get; set; } = string.Empty; + public string? TaxId { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + + public Address? Address { get; set; } + + public string? PreferredLanguage { get; set; } + } + + // ====================== DocumentHeader ====================== + + public sealed class DocumentHeader + { + // Guid serialized as bytes + public byte[] DocId { get; set; } = Array.Empty(); + + public DocType Type { get; set; } + public int Version { get; set; } + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + + public Currency Currency { get; set; } + + public string? Notes { get; set; } + + // corresponds to Dictionary + public Dictionary Meta { get; set; } = new(); + } + + // ====================== LineItem, Payment, Attachment ====================== + + public sealed class LineItem + { + public int LineNo { get; set; } + public LineType Type { get; set; } + + public string SKU { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + + public double Qty { get; set; } + public string QtyUnit { get; set; } = string.Empty; + + public double UnitPrice { get; set; } + + public double? VatRate { get; set; } + public double? Discount { get; set; } + + // Dictionary + public Dictionary Ext { get; set; } = new(); + } + + public sealed class Payment + { + public PaymentMethod Method { get; set; } + + public double Amount { get; set; } + public string? Reference { get; set; } + + public DateTime Timestamp { get; set; } + + public double? Fee { get; set; } + + public Currency Currency { get; set; } + } + + public sealed class Attachment + { + public string Name { get; set; } = string.Empty; + public string MimeType { get; set; } = string.Empty; + public byte[] Data { get; set; } = Array.Empty(); + } + + // ====================== Top-level BusinessDocument ====================== + + public sealed class BusinessDocument + { + public DocumentHeader Header { get; set; } = new DocumentHeader(); + + public Party Seller { get; set; } = new Party(); + public Party Buyer { get; set; } = new Party(); + + public LineItem[] Items { get; set; } = Array.Empty(); + public Payment[] Payments { get; set; } = Array.Empty(); + public Attachment[] Attachments { get; set; } = Array.Empty(); + + public int[] RiskScores { get; set; } = Array.Empty(); + } +} diff --git a/Tests/RPC/Client/Model/Thrift/Address.cs b/Tests/RPC/Client/Model/Thrift/Address.cs new file mode 100644 index 0000000..e0f313e --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Address.cs @@ -0,0 +1,428 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Address : TBase + { + private string _line1; + private string _line2; + private string _city; + private string _region; + private string _country; + private string _postalCode; + + public string Line1 + { + get + { + return _line1; + } + set + { + __isset.line1 = true; + this._line1 = value; + } + } + + public string Line2 + { + get + { + return _line2; + } + set + { + __isset.line2 = true; + this._line2 = value; + } + } + + public string City + { + get + { + return _city; + } + set + { + __isset.@city = true; + this._city = value; + } + } + + public string Region + { + get + { + return _region; + } + set + { + __isset.@region = true; + this._region = value; + } + } + + public string Country + { + get + { + return _country; + } + set + { + __isset.@country = true; + this._country = value; + } + } + + public string PostalCode + { + get + { + return _postalCode; + } + set + { + __isset.postalCode = true; + this._postalCode = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool line1; + public bool line2; + public bool @city; + public bool @region; + public bool @country; + public bool postalCode; + } + + public Address() + { + } + + public Address DeepCopy() + { + var tmp15 = new Address(); + if((Line1 != null) && __isset.line1) + { + tmp15.Line1 = this.Line1; + } + tmp15.__isset.line1 = this.__isset.line1; + if((Line2 != null) && __isset.line2) + { + tmp15.Line2 = this.Line2; + } + tmp15.__isset.line2 = this.__isset.line2; + if((City != null) && __isset.@city) + { + tmp15.City = this.City; + } + tmp15.__isset.@city = this.__isset.@city; + if((Region != null) && __isset.@region) + { + tmp15.Region = this.Region; + } + tmp15.__isset.@region = this.__isset.@region; + if((Country != null) && __isset.@country) + { + tmp15.Country = this.Country; + } + tmp15.__isset.@country = this.__isset.@country; + if((PostalCode != null) && __isset.postalCode) + { + tmp15.PostalCode = this.PostalCode; + } + tmp15.__isset.postalCode = this.__isset.postalCode; + return tmp15; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Line1 = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + Line2 = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + City = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Region = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.String) + { + Country = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + PostalCode = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp16 = new TStruct("Address"); + await oprot.WriteStructBeginAsync(tmp16, cancellationToken); + var tmp17 = new TField(); + if((Line1 != null) && __isset.line1) + { + tmp17.Name = "line1"; + tmp17.Type = TType.String; + tmp17.ID = 1; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Line1, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Line2 != null) && __isset.line2) + { + tmp17.Name = "line2"; + tmp17.Type = TType.String; + tmp17.ID = 2; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Line2, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((City != null) && __isset.@city) + { + tmp17.Name = "city"; + tmp17.Type = TType.String; + tmp17.ID = 3; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(City, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Region != null) && __isset.@region) + { + tmp17.Name = "region"; + tmp17.Type = TType.String; + tmp17.ID = 4; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Region, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Country != null) && __isset.@country) + { + tmp17.Name = "country"; + tmp17.Type = TType.String; + tmp17.ID = 5; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Country, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((PostalCode != null) && __isset.postalCode) + { + tmp17.Name = "postalCode"; + tmp17.Type = TType.String; + tmp17.ID = 6; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(PostalCode, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Address other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.line1 == other.__isset.line1) && ((!__isset.line1) || (global::System.Object.Equals(Line1, other.Line1)))) + && ((__isset.line2 == other.__isset.line2) && ((!__isset.line2) || (global::System.Object.Equals(Line2, other.Line2)))) + && ((__isset.@city == other.__isset.@city) && ((!__isset.@city) || (global::System.Object.Equals(City, other.City)))) + && ((__isset.@region == other.__isset.@region) && ((!__isset.@region) || (global::System.Object.Equals(Region, other.Region)))) + && ((__isset.@country == other.__isset.@country) && ((!__isset.@country) || (global::System.Object.Equals(Country, other.Country)))) + && ((__isset.postalCode == other.__isset.postalCode) && ((!__isset.postalCode) || (global::System.Object.Equals(PostalCode, other.PostalCode)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Line1 != null) && __isset.line1) + { + hashcode = (hashcode * 397) + Line1.GetHashCode(); + } + if((Line2 != null) && __isset.line2) + { + hashcode = (hashcode * 397) + Line2.GetHashCode(); + } + if((City != null) && __isset.@city) + { + hashcode = (hashcode * 397) + City.GetHashCode(); + } + if((Region != null) && __isset.@region) + { + hashcode = (hashcode * 397) + Region.GetHashCode(); + } + if((Country != null) && __isset.@country) + { + hashcode = (hashcode * 397) + Country.GetHashCode(); + } + if((PostalCode != null) && __isset.postalCode) + { + hashcode = (hashcode * 397) + PostalCode.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp18 = new StringBuilder("Address("); + int tmp19 = 0; + if((Line1 != null) && __isset.line1) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Line1: "); + Line1.ToString(tmp18); + } + if((Line2 != null) && __isset.line2) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Line2: "); + Line2.ToString(tmp18); + } + if((City != null) && __isset.@city) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("City: "); + City.ToString(tmp18); + } + if((Region != null) && __isset.@region) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Region: "); + Region.ToString(tmp18); + } + if((Country != null) && __isset.@country) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Country: "); + Country.ToString(tmp18); + } + if((PostalCode != null) && __isset.postalCode) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("PostalCode: "); + PostalCode.ToString(tmp18); + } + tmp18.Append(')'); + return tmp18.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/Attachment.cs b/Tests/RPC/Client/Model/Thrift/Attachment.cs new file mode 100644 index 0000000..8fb4fa6 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Attachment.cs @@ -0,0 +1,278 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Attachment : TBase + { + private string _name; + private string _mimeType; + private byte[] _data; + + public string Name + { + get + { + return _name; + } + set + { + __isset.@name = true; + this._name = value; + } + } + + public string MimeType + { + get + { + return _mimeType; + } + set + { + __isset.mimeType = true; + this._mimeType = value; + } + } + + public byte[] Data + { + get + { + return _data; + } + set + { + __isset.@data = true; + this._data = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @name; + public bool mimeType; + public bool @data; + } + + public Attachment() + { + } + + public Attachment DeepCopy() + { + var tmp50 = new Attachment(); + if((Name != null) && __isset.@name) + { + tmp50.Name = this.Name; + } + tmp50.__isset.@name = this.__isset.@name; + if((MimeType != null) && __isset.mimeType) + { + tmp50.MimeType = this.MimeType; + } + tmp50.__isset.mimeType = this.__isset.mimeType; + if((Data != null) && __isset.@data) + { + tmp50.Data = this.Data.ToArray(); + } + tmp50.__isset.@data = this.__isset.@data; + return tmp50; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Name = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + MimeType = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Data = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp51 = new TStruct("Attachment"); + await oprot.WriteStructBeginAsync(tmp51, cancellationToken); + var tmp52 = new TField(); + if((Name != null) && __isset.@name) + { + tmp52.Name = "name"; + tmp52.Type = TType.String; + tmp52.ID = 1; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteStringAsync(Name, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((MimeType != null) && __isset.mimeType) + { + tmp52.Name = "mimeType"; + tmp52.Type = TType.String; + tmp52.ID = 2; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteStringAsync(MimeType, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Data != null) && __isset.@data) + { + tmp52.Name = "data"; + tmp52.Type = TType.String; + tmp52.ID = 3; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteBinaryAsync(Data, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Attachment other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@name == other.__isset.@name) && ((!__isset.@name) || (global::System.Object.Equals(Name, other.Name)))) + && ((__isset.mimeType == other.__isset.mimeType) && ((!__isset.mimeType) || (global::System.Object.Equals(MimeType, other.MimeType)))) + && ((__isset.@data == other.__isset.@data) && ((!__isset.@data) || (TCollections.Equals(Data, other.Data)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Name != null) && __isset.@name) + { + hashcode = (hashcode * 397) + Name.GetHashCode(); + } + if((MimeType != null) && __isset.mimeType) + { + hashcode = (hashcode * 397) + MimeType.GetHashCode(); + } + if((Data != null) && __isset.@data) + { + hashcode = (hashcode * 397) + Data.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp53 = new StringBuilder("Attachment("); + int tmp54 = 0; + if((Name != null) && __isset.@name) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("Name: "); + Name.ToString(tmp53); + } + if((MimeType != null) && __isset.mimeType) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("MimeType: "); + MimeType.ToString(tmp53); + } + if((Data != null) && __isset.@data) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("Data: "); + Data.ToString(tmp53); + } + tmp53.Append(')'); + return tmp53.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/BusinessDocument.cs b/Tests/RPC/Client/Model/Thrift/BusinessDocument.cs new file mode 100644 index 0000000..ae3eb18 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/BusinessDocument.cs @@ -0,0 +1,544 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class BusinessDocument : TBase + { + private global::Echo.ThriftModel.DocumentHeader _header; + private global::Echo.ThriftModel.Party _seller; + private global::Echo.ThriftModel.Party _buyer; + private List _items; + private List _payments; + private List _attachments; + private List _riskScores; + + public global::Echo.ThriftModel.DocumentHeader Header + { + get + { + return _header; + } + set + { + __isset.@header = true; + this._header = value; + } + } + + public global::Echo.ThriftModel.Party Seller + { + get + { + return _seller; + } + set + { + __isset.@seller = true; + this._seller = value; + } + } + + public global::Echo.ThriftModel.Party Buyer + { + get + { + return _buyer; + } + set + { + __isset.@buyer = true; + this._buyer = value; + } + } + + public List Items + { + get + { + return _items; + } + set + { + __isset.@items = true; + this._items = value; + } + } + + public List Payments + { + get + { + return _payments; + } + set + { + __isset.@payments = true; + this._payments = value; + } + } + + public List Attachments + { + get + { + return _attachments; + } + set + { + __isset.@attachments = true; + this._attachments = value; + } + } + + public List RiskScores + { + get + { + return _riskScores; + } + set + { + __isset.riskScores = true; + this._riskScores = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @header; + public bool @seller; + public bool @buyer; + public bool @items; + public bool @payments; + public bool @attachments; + public bool riskScores; + } + + public BusinessDocument() + { + } + + public BusinessDocument DeepCopy() + { + var tmp55 = new BusinessDocument(); + if((Header != null) && __isset.@header) + { + tmp55.Header = (global::Echo.ThriftModel.DocumentHeader)this.Header.DeepCopy(); + } + tmp55.__isset.@header = this.__isset.@header; + if((Seller != null) && __isset.@seller) + { + tmp55.Seller = (global::Echo.ThriftModel.Party)this.Seller.DeepCopy(); + } + tmp55.__isset.@seller = this.__isset.@seller; + if((Buyer != null) && __isset.@buyer) + { + tmp55.Buyer = (global::Echo.ThriftModel.Party)this.Buyer.DeepCopy(); + } + tmp55.__isset.@buyer = this.__isset.@buyer; + if((Items != null) && __isset.@items) + { + tmp55.Items = this.Items.DeepCopy(); + } + tmp55.__isset.@items = this.__isset.@items; + if((Payments != null) && __isset.@payments) + { + tmp55.Payments = this.Payments.DeepCopy(); + } + tmp55.__isset.@payments = this.__isset.@payments; + if((Attachments != null) && __isset.@attachments) + { + tmp55.Attachments = this.Attachments.DeepCopy(); + } + tmp55.__isset.@attachments = this.__isset.@attachments; + if((RiskScores != null) && __isset.riskScores) + { + tmp55.RiskScores = this.RiskScores.DeepCopy(); + } + tmp55.__isset.riskScores = this.__isset.riskScores; + return tmp55; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.Struct) + { + Header = new global::Echo.ThriftModel.DocumentHeader(); + await Header.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Seller = new global::Echo.ThriftModel.Party(); + await Seller.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.Struct) + { + Buyer = new global::Echo.ThriftModel.Party(); + await Buyer.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.List) + { + { + var _list56 = await iprot.ReadListBeginAsync(cancellationToken); + Items = new List(_list56.Count); + for(int _i57 = 0; _i57 < _list56.Count; ++_i57) + { + global::Echo.ThriftModel.LineItem _elem58; + _elem58 = new global::Echo.ThriftModel.LineItem(); + await _elem58.ReadAsync(iprot, cancellationToken); + Items.Add(_elem58); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.List) + { + { + var _list59 = await iprot.ReadListBeginAsync(cancellationToken); + Payments = new List(_list59.Count); + for(int _i60 = 0; _i60 < _list59.Count; ++_i60) + { + global::Echo.ThriftModel.Payment _elem61; + _elem61 = new global::Echo.ThriftModel.Payment(); + await _elem61.ReadAsync(iprot, cancellationToken); + Payments.Add(_elem61); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.List) + { + { + var _list62 = await iprot.ReadListBeginAsync(cancellationToken); + Attachments = new List(_list62.Count); + for(int _i63 = 0; _i63 < _list62.Count; ++_i63) + { + global::Echo.ThriftModel.Attachment _elem64; + _elem64 = new global::Echo.ThriftModel.Attachment(); + await _elem64.ReadAsync(iprot, cancellationToken); + Attachments.Add(_elem64); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.List) + { + { + var _list65 = await iprot.ReadListBeginAsync(cancellationToken); + RiskScores = new List(_list65.Count); + for(int _i66 = 0; _i66 < _list65.Count; ++_i66) + { + int _elem67; + _elem67 = await iprot.ReadI32Async(cancellationToken); + RiskScores.Add(_elem67); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp68 = new TStruct("BusinessDocument"); + await oprot.WriteStructBeginAsync(tmp68, cancellationToken); + var tmp69 = new TField(); + if((Header != null) && __isset.@header) + { + tmp69.Name = "header"; + tmp69.Type = TType.Struct; + tmp69.ID = 1; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Header.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Seller != null) && __isset.@seller) + { + tmp69.Name = "seller"; + tmp69.Type = TType.Struct; + tmp69.ID = 2; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Seller.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Buyer != null) && __isset.@buyer) + { + tmp69.Name = "buyer"; + tmp69.Type = TType.Struct; + tmp69.ID = 3; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Buyer.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Items != null) && __isset.@items) + { + tmp69.Name = "items"; + tmp69.Type = TType.List; + tmp69.ID = 4; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Items.Count), cancellationToken); + foreach (global::Echo.ThriftModel.LineItem _iter70 in Items) + { + await _iter70.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Payments != null) && __isset.@payments) + { + tmp69.Name = "payments"; + tmp69.Type = TType.List; + tmp69.ID = 5; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Payments.Count), cancellationToken); + foreach (global::Echo.ThriftModel.Payment _iter71 in Payments) + { + await _iter71.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Attachments != null) && __isset.@attachments) + { + tmp69.Name = "attachments"; + tmp69.Type = TType.List; + tmp69.ID = 6; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Attachments.Count), cancellationToken); + foreach (global::Echo.ThriftModel.Attachment _iter72 in Attachments) + { + await _iter72.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((RiskScores != null) && __isset.riskScores) + { + tmp69.Name = "riskScores"; + tmp69.Type = TType.List; + tmp69.ID = 7; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, RiskScores.Count), cancellationToken); + foreach (int _iter73 in RiskScores) + { + await oprot.WriteI32Async(_iter73, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is BusinessDocument other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@header == other.__isset.@header) && ((!__isset.@header) || (global::System.Object.Equals(Header, other.Header)))) + && ((__isset.@seller == other.__isset.@seller) && ((!__isset.@seller) || (global::System.Object.Equals(Seller, other.Seller)))) + && ((__isset.@buyer == other.__isset.@buyer) && ((!__isset.@buyer) || (global::System.Object.Equals(Buyer, other.Buyer)))) + && ((__isset.@items == other.__isset.@items) && ((!__isset.@items) || (TCollections.Equals(Items, other.Items)))) + && ((__isset.@payments == other.__isset.@payments) && ((!__isset.@payments) || (TCollections.Equals(Payments, other.Payments)))) + && ((__isset.@attachments == other.__isset.@attachments) && ((!__isset.@attachments) || (TCollections.Equals(Attachments, other.Attachments)))) + && ((__isset.riskScores == other.__isset.riskScores) && ((!__isset.riskScores) || (TCollections.Equals(RiskScores, other.RiskScores)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Header != null) && __isset.@header) + { + hashcode = (hashcode * 397) + Header.GetHashCode(); + } + if((Seller != null) && __isset.@seller) + { + hashcode = (hashcode * 397) + Seller.GetHashCode(); + } + if((Buyer != null) && __isset.@buyer) + { + hashcode = (hashcode * 397) + Buyer.GetHashCode(); + } + if((Items != null) && __isset.@items) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Items); + } + if((Payments != null) && __isset.@payments) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Payments); + } + if((Attachments != null) && __isset.@attachments) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Attachments); + } + if((RiskScores != null) && __isset.riskScores) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(RiskScores); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp74 = new StringBuilder("BusinessDocument("); + int tmp75 = 0; + if((Header != null) && __isset.@header) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Header: "); + Header.ToString(tmp74); + } + if((Seller != null) && __isset.@seller) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Seller: "); + Seller.ToString(tmp74); + } + if((Buyer != null) && __isset.@buyer) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Buyer: "); + Buyer.ToString(tmp74); + } + if((Items != null) && __isset.@items) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Items: "); + Items.ToString(tmp74); + } + if((Payments != null) && __isset.@payments) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Payments: "); + Payments.ToString(tmp74); + } + if((Attachments != null) && __isset.@attachments) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Attachments: "); + Attachments.ToString(tmp74); + } + if((RiskScores != null) && __isset.riskScores) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("RiskScores: "); + RiskScores.ToString(tmp74); + } + tmp74.Append(')'); + return tmp74.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/Currency.cs b/Tests/RPC/Client/Model/Thrift/Currency.cs new file mode 100644 index 0000000..1e84e42 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Currency.cs @@ -0,0 +1,26 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum Currency + { + IQD = 0, + CNH = 1, + USD = 2, + EUR = 3, + JPY = 4, + GBP = 5, + } +} diff --git a/Tests/RPC/Client/Model/Thrift/DocType.cs b/Tests/RPC/Client/Model/Thrift/DocType.cs new file mode 100644 index 0000000..753771b --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/DocType.cs @@ -0,0 +1,24 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum DocType + { + Quote = 0, + Order = 1, + Invoice = 2, + CreditNote = 3, + } +} diff --git a/Tests/RPC/Client/Model/Thrift/DocumentHeader.cs b/Tests/RPC/Client/Model/Thrift/DocumentHeader.cs new file mode 100644 index 0000000..e578a5d --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/DocumentHeader.cs @@ -0,0 +1,555 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class DocumentHeader : TBase + { + private byte[] _docId; + private global::Echo.ThriftModel.DocType _type; + private int _version; + private long _createdAt; + private long _updatedAt; + private global::Echo.ThriftModel.Currency _currency; + private string _notes; + private Dictionary _meta; + + public byte[] DocId + { + get + { + return _docId; + } + set + { + __isset.docId = true; + this._docId = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.DocType Type + { + get + { + return _type; + } + set + { + __isset.@type = true; + this._type = value; + } + } + + public int Version + { + get + { + return _version; + } + set + { + __isset.@version = true; + this._version = value; + } + } + + public long CreatedAt + { + get + { + return _createdAt; + } + set + { + __isset.createdAt = true; + this._createdAt = value; + } + } + + public long UpdatedAt + { + get + { + return _updatedAt; + } + set + { + __isset.updatedAt = true; + this._updatedAt = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.Currency Currency + { + get + { + return _currency; + } + set + { + __isset.@currency = true; + this._currency = value; + } + } + + public string Notes + { + get + { + return _notes; + } + set + { + __isset.@notes = true; + this._notes = value; + } + } + + public Dictionary Meta + { + get + { + return _meta; + } + set + { + __isset.@meta = true; + this._meta = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool docId; + public bool @type; + public bool @version; + public bool createdAt; + public bool updatedAt; + public bool @currency; + public bool @notes; + public bool @meta; + } + + public DocumentHeader() + { + } + + public DocumentHeader DeepCopy() + { + var tmp25 = new DocumentHeader(); + if((DocId != null) && __isset.docId) + { + tmp25.DocId = this.DocId.ToArray(); + } + tmp25.__isset.docId = this.__isset.docId; + if(__isset.@type) + { + tmp25.Type = this.Type; + } + tmp25.__isset.@type = this.__isset.@type; + if(__isset.@version) + { + tmp25.Version = this.Version; + } + tmp25.__isset.@version = this.__isset.@version; + if(__isset.createdAt) + { + tmp25.CreatedAt = this.CreatedAt; + } + tmp25.__isset.createdAt = this.__isset.createdAt; + if(__isset.updatedAt) + { + tmp25.UpdatedAt = this.UpdatedAt; + } + tmp25.__isset.updatedAt = this.__isset.updatedAt; + if(__isset.@currency) + { + tmp25.Currency = this.Currency; + } + tmp25.__isset.@currency = this.__isset.@currency; + if((Notes != null) && __isset.@notes) + { + tmp25.Notes = this.Notes; + } + tmp25.__isset.@notes = this.__isset.@notes; + if((Meta != null) && __isset.@meta) + { + tmp25.Meta = this.Meta.DeepCopy(); + } + tmp25.__isset.@meta = this.__isset.@meta; + return tmp25; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + DocId = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.I32) + { + Type = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.I32) + { + Version = await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + CreatedAt = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.I64) + { + UpdatedAt = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.I32) + { + Currency = (global::Echo.ThriftModel.Currency)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + Notes = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.Map) + { + { + var _map26 = await iprot.ReadMapBeginAsync(cancellationToken); + Meta = new Dictionary(_map26.Count); + for(int _i27 = 0; _i27 < _map26.Count; ++_i27) + { + string _key28; + global::Echo.ThriftModel.Variant _val29; + _key28 = await iprot.ReadStringAsync(cancellationToken); + _val29 = new global::Echo.ThriftModel.Variant(); + await _val29.ReadAsync(iprot, cancellationToken); + Meta[_key28] = _val29; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp30 = new TStruct("DocumentHeader"); + await oprot.WriteStructBeginAsync(tmp30, cancellationToken); + var tmp31 = new TField(); + if((DocId != null) && __isset.docId) + { + tmp31.Name = "docId"; + tmp31.Type = TType.String; + tmp31.ID = 1; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteBinaryAsync(DocId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@type) + { + tmp31.Name = "type"; + tmp31.Type = TType.I32; + tmp31.ID = 2; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async((int)Type, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@version) + { + tmp31.Name = "version"; + tmp31.Type = TType.I32; + tmp31.ID = 3; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async(Version, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.createdAt) + { + tmp31.Name = "createdAt"; + tmp31.Type = TType.I64; + tmp31.ID = 4; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI64Async(CreatedAt, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.updatedAt) + { + tmp31.Name = "updatedAt"; + tmp31.Type = TType.I64; + tmp31.ID = 5; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI64Async(UpdatedAt, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@currency) + { + tmp31.Name = "currency"; + tmp31.Type = TType.I32; + tmp31.ID = 6; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async((int)Currency, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Notes != null) && __isset.@notes) + { + tmp31.Name = "notes"; + tmp31.Type = TType.String; + tmp31.ID = 7; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteStringAsync(Notes, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Meta != null) && __isset.@meta) + { + tmp31.Name = "meta"; + tmp31.Type = TType.Map; + tmp31.ID = 8; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Meta.Count), cancellationToken); + foreach (string _iter32 in Meta.Keys) + { + await oprot.WriteStringAsync(_iter32, cancellationToken); + await Meta[_iter32].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is DocumentHeader other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.docId == other.__isset.docId) && ((!__isset.docId) || (TCollections.Equals(DocId, other.DocId)))) + && ((__isset.@type == other.__isset.@type) && ((!__isset.@type) || (global::System.Object.Equals(Type, other.Type)))) + && ((__isset.@version == other.__isset.@version) && ((!__isset.@version) || (global::System.Object.Equals(Version, other.Version)))) + && ((__isset.createdAt == other.__isset.createdAt) && ((!__isset.createdAt) || (global::System.Object.Equals(CreatedAt, other.CreatedAt)))) + && ((__isset.updatedAt == other.__isset.updatedAt) && ((!__isset.updatedAt) || (global::System.Object.Equals(UpdatedAt, other.UpdatedAt)))) + && ((__isset.@currency == other.__isset.@currency) && ((!__isset.@currency) || (global::System.Object.Equals(Currency, other.Currency)))) + && ((__isset.@notes == other.__isset.@notes) && ((!__isset.@notes) || (global::System.Object.Equals(Notes, other.Notes)))) + && ((__isset.@meta == other.__isset.@meta) && ((!__isset.@meta) || (TCollections.Equals(Meta, other.Meta)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((DocId != null) && __isset.docId) + { + hashcode = (hashcode * 397) + DocId.GetHashCode(); + } + if(__isset.@type) + { + hashcode = (hashcode * 397) + Type.GetHashCode(); + } + if(__isset.@version) + { + hashcode = (hashcode * 397) + Version.GetHashCode(); + } + if(__isset.createdAt) + { + hashcode = (hashcode * 397) + CreatedAt.GetHashCode(); + } + if(__isset.updatedAt) + { + hashcode = (hashcode * 397) + UpdatedAt.GetHashCode(); + } + if(__isset.@currency) + { + hashcode = (hashcode * 397) + Currency.GetHashCode(); + } + if((Notes != null) && __isset.@notes) + { + hashcode = (hashcode * 397) + Notes.GetHashCode(); + } + if((Meta != null) && __isset.@meta) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Meta); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp33 = new StringBuilder("DocumentHeader("); + int tmp34 = 0; + if((DocId != null) && __isset.docId) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("DocId: "); + DocId.ToString(tmp33); + } + if(__isset.@type) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Type: "); + Type.ToString(tmp33); + } + if(__isset.@version) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Version: "); + Version.ToString(tmp33); + } + if(__isset.createdAt) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("CreatedAt: "); + CreatedAt.ToString(tmp33); + } + if(__isset.updatedAt) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("UpdatedAt: "); + UpdatedAt.ToString(tmp33); + } + if(__isset.@currency) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Currency: "); + Currency.ToString(tmp33); + } + if((Notes != null) && __isset.@notes) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Notes: "); + Notes.ToString(tmp33); + } + if((Meta != null) && __isset.@meta) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Meta: "); + Meta.ToString(tmp33); + } + tmp33.Append(')'); + return tmp33.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/EchoService.cs b/Tests/RPC/Client/Model/Thrift/EchoService.cs new file mode 100644 index 0000000..0a536ee --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/EchoService.cs @@ -0,0 +1,2444 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public partial class EchoService + { + public interface IAsync + { + global::System.Threading.Tasks.Task EchoBytes(byte[] @data, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoDocuments(List @docs, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoIntArray(List @array, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoStringArray(List @array, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoMap(Dictionary @map, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoEnumArray(List docTypes, CancellationToken cancellationToken = default); + + } + + + public class Client : TBaseClient, IDisposable, IAsync + { + public Client(TProtocol protocol) : this(protocol, protocol) + { + } + + public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol) + { + } + + public async global::System.Threading.Tasks.Task EchoBytes(byte[] @data, CancellationToken cancellationToken = default) + { + await send_EchoBytes(@data, cancellationToken); + return await recv_EchoBytes(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoBytes(byte[] @data, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Call, SeqId), cancellationToken); + + var tmp76 = new InternalStructs.EchoBytes_args() { + Data = @data, + }; + + await tmp76.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task recv_EchoBytes(CancellationToken cancellationToken = default) + { + + var tmp77 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp77.Type == TMessageType.Exception) + { + var tmp78 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp78; + } + + var tmp79 = new InternalStructs.EchoBytes_result(); + await tmp79.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp79.__isset.success) + { + return tmp79.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoBytes failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoDocuments(List @docs, CancellationToken cancellationToken = default) + { + await send_EchoDocuments(@docs, cancellationToken); + return await recv_EchoDocuments(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoDocuments(List @docs, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Call, SeqId), cancellationToken); + + var tmp80 = new InternalStructs.EchoDocuments_args() { + Docs = @docs, + }; + + await tmp80.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoDocuments(CancellationToken cancellationToken = default) + { + + var tmp81 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp81.Type == TMessageType.Exception) + { + var tmp82 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp82; + } + + var tmp83 = new InternalStructs.EchoDocuments_result(); + await tmp83.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp83.__isset.success) + { + return tmp83.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoDocuments failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoIntArray(List @array, CancellationToken cancellationToken = default) + { + await send_EchoIntArray(@array, cancellationToken); + return await recv_EchoIntArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoIntArray(List @array, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp84 = new InternalStructs.EchoIntArray_args() { + Array = @array, + }; + + await tmp84.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoIntArray(CancellationToken cancellationToken = default) + { + + var tmp85 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp85.Type == TMessageType.Exception) + { + var tmp86 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp86; + } + + var tmp87 = new InternalStructs.EchoIntArray_result(); + await tmp87.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp87.__isset.success) + { + return tmp87.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoIntArray failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoStringArray(List @array, CancellationToken cancellationToken = default) + { + await send_EchoStringArray(@array, cancellationToken); + return await recv_EchoStringArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoStringArray(List @array, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp88 = new InternalStructs.EchoStringArray_args() { + Array = @array, + }; + + await tmp88.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoStringArray(CancellationToken cancellationToken = default) + { + + var tmp89 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp89.Type == TMessageType.Exception) + { + var tmp90 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp90; + } + + var tmp91 = new InternalStructs.EchoStringArray_result(); + await tmp91.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp91.__isset.success) + { + return tmp91.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoStringArray failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoMap(Dictionary @map, CancellationToken cancellationToken = default) + { + await send_EchoMap(@map, cancellationToken); + return await recv_EchoMap(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoMap(Dictionary @map, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Call, SeqId), cancellationToken); + + var tmp92 = new InternalStructs.EchoMap_args() { + Map = @map, + }; + + await tmp92.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoMap(CancellationToken cancellationToken = default) + { + + var tmp93 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp93.Type == TMessageType.Exception) + { + var tmp94 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp94; + } + + var tmp95 = new InternalStructs.EchoMap_result(); + await tmp95.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp95.__isset.success) + { + return tmp95.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoMap failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoEnumArray(List docTypes, CancellationToken cancellationToken = default) + { + await send_EchoEnumArray(docTypes, cancellationToken); + return await recv_EchoEnumArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoEnumArray(List docTypes, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp96 = new InternalStructs.EchoEnumArray_args() { + DocTypes = docTypes, + }; + + await tmp96.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoEnumArray(CancellationToken cancellationToken = default) + { + + var tmp97 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp97.Type == TMessageType.Exception) + { + var tmp98 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp98; + } + + var tmp99 = new InternalStructs.EchoEnumArray_result(); + await tmp99.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp99.__isset.success) + { + return tmp99.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoEnumArray failed: unknown result"); + } + + } + + public class AsyncProcessor : ITAsyncProcessor + { + private readonly IAsync _iAsync; + private readonly ILogger _logger; + + public AsyncProcessor(IAsync iAsync, ILogger logger = default) + { + _iAsync = iAsync ?? throw new ArgumentNullException(nameof(iAsync)); + _logger = logger; + processMap_["EchoBytes"] = EchoBytes_ProcessAsync; + processMap_["EchoDocuments"] = EchoDocuments_ProcessAsync; + processMap_["EchoIntArray"] = EchoIntArray_ProcessAsync; + processMap_["EchoStringArray"] = EchoStringArray_ProcessAsync; + processMap_["EchoMap"] = EchoMap_ProcessAsync; + processMap_["EchoEnumArray"] = EchoEnumArray_ProcessAsync; + } + + protected delegate global::System.Threading.Tasks.Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken); + protected Dictionary processMap_ = new Dictionary(); + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) + { + return await ProcessAsync(iprot, oprot, CancellationToken.None); + } + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + try + { + var msg = await iprot.ReadMessageBeginAsync(cancellationToken); + + processMap_.TryGetValue(msg.Name, out var fn); + + if (fn == null) + { + await TProtocolUtil.SkipAsync(iprot, TType.Struct, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: '" + msg.Name + "'"); + await oprot.WriteMessageBeginAsync(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID), cancellationToken); + await x.WriteAsync(oprot, cancellationToken); + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + return true; + } + + await fn(msg.SeqID, iprot, oprot, cancellationToken); + + } + catch (IOException) + { + return false; + } + + return true; + } + + public async global::System.Threading.Tasks.Task EchoBytes_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp100 = new InternalStructs.EchoBytes_args(); + await tmp100.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp101 = new InternalStructs.EchoBytes_result(); + try + { + tmp101.Success = await _iAsync.EchoBytes(tmp100.Data, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Reply, seqid), cancellationToken); + await tmp101.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp102) + { + var tmp103 = $"Error occurred in {GetType().FullName}: {tmp102.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp102, tmp103); + else + Console.Error.WriteLine(tmp103); + var tmp104 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Exception, seqid), cancellationToken); + await tmp104.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoDocuments_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp105 = new InternalStructs.EchoDocuments_args(); + await tmp105.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp106 = new InternalStructs.EchoDocuments_result(); + try + { + tmp106.Success = await _iAsync.EchoDocuments(tmp105.Docs, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Reply, seqid), cancellationToken); + await tmp106.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp107) + { + var tmp108 = $"Error occurred in {GetType().FullName}: {tmp107.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp107, tmp108); + else + Console.Error.WriteLine(tmp108); + var tmp109 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Exception, seqid), cancellationToken); + await tmp109.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoIntArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp110 = new InternalStructs.EchoIntArray_args(); + await tmp110.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp111 = new InternalStructs.EchoIntArray_result(); + try + { + tmp111.Success = await _iAsync.EchoIntArray(tmp110.Array, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Reply, seqid), cancellationToken); + await tmp111.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp112) + { + var tmp113 = $"Error occurred in {GetType().FullName}: {tmp112.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp112, tmp113); + else + Console.Error.WriteLine(tmp113); + var tmp114 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Exception, seqid), cancellationToken); + await tmp114.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoStringArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp115 = new InternalStructs.EchoStringArray_args(); + await tmp115.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp116 = new InternalStructs.EchoStringArray_result(); + try + { + tmp116.Success = await _iAsync.EchoStringArray(tmp115.Array, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Reply, seqid), cancellationToken); + await tmp116.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp117) + { + var tmp118 = $"Error occurred in {GetType().FullName}: {tmp117.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp117, tmp118); + else + Console.Error.WriteLine(tmp118); + var tmp119 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Exception, seqid), cancellationToken); + await tmp119.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoMap_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp120 = new InternalStructs.EchoMap_args(); + await tmp120.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp121 = new InternalStructs.EchoMap_result(); + try + { + tmp121.Success = await _iAsync.EchoMap(tmp120.Map, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Reply, seqid), cancellationToken); + await tmp121.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp122) + { + var tmp123 = $"Error occurred in {GetType().FullName}: {tmp122.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp122, tmp123); + else + Console.Error.WriteLine(tmp123); + var tmp124 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Exception, seqid), cancellationToken); + await tmp124.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoEnumArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp125 = new InternalStructs.EchoEnumArray_args(); + await tmp125.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp126 = new InternalStructs.EchoEnumArray_result(); + try + { + tmp126.Success = await _iAsync.EchoEnumArray(tmp125.DocTypes, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Reply, seqid), cancellationToken); + await tmp126.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp127) + { + var tmp128 = $"Error occurred in {GetType().FullName}: {tmp127.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp127, tmp128); + else + Console.Error.WriteLine(tmp128); + var tmp129 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Exception, seqid), cancellationToken); + await tmp129.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + } + + public class InternalStructs + { + + public partial class EchoBytes_args : TBase + { + private byte[] _data; + + public byte[] Data + { + get + { + return _data; + } + set + { + __isset.@data = true; + this._data = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @data; + } + + public EchoBytes_args() + { + } + + public EchoBytes_args DeepCopy() + { + var tmp130 = new EchoBytes_args(); + if((Data != null) && __isset.@data) + { + tmp130.Data = this.Data.ToArray(); + } + tmp130.__isset.@data = this.__isset.@data; + return tmp130; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Data = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp131 = new TStruct("EchoBytes_args"); + await oprot.WriteStructBeginAsync(tmp131, cancellationToken); + var tmp132 = new TField(); + if((Data != null) && __isset.@data) + { + tmp132.Name = "data"; + tmp132.Type = TType.String; + tmp132.ID = 1; + await oprot.WriteFieldBeginAsync(tmp132, cancellationToken); + await oprot.WriteBinaryAsync(Data, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoBytes_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@data == other.__isset.@data) && ((!__isset.@data) || (TCollections.Equals(Data, other.Data)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Data != null) && __isset.@data) + { + hashcode = (hashcode * 397) + Data.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp133 = new StringBuilder("EchoBytes_args("); + int tmp134 = 0; + if((Data != null) && __isset.@data) + { + if(0 < tmp134++) { tmp133.Append(", "); } + tmp133.Append("Data: "); + Data.ToString(tmp133); + } + tmp133.Append(')'); + return tmp133.ToString(); + } + } + + + public partial class EchoBytes_result : TBase + { + private byte[] _success; + + public byte[] Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoBytes_result() + { + } + + public EchoBytes_result DeepCopy() + { + var tmp135 = new EchoBytes_result(); + if((Success != null) && __isset.@success) + { + tmp135.Success = this.Success.ToArray(); + } + tmp135.__isset.@success = this.__isset.@success; + return tmp135; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.String) + { + Success = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp136 = new TStruct("EchoBytes_result"); + await oprot.WriteStructBeginAsync(tmp136, cancellationToken); + var tmp137 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp137.Name = "Success"; + tmp137.Type = TType.String; + tmp137.ID = 0; + await oprot.WriteFieldBeginAsync(tmp137, cancellationToken); + await oprot.WriteBinaryAsync(Success, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoBytes_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + Success.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp138 = new StringBuilder("EchoBytes_result("); + int tmp139 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp139++) { tmp138.Append(", "); } + tmp138.Append("Success: "); + Success.ToString(tmp138); + } + tmp138.Append(')'); + return tmp138.ToString(); + } + } + + + public partial class EchoDocuments_args : TBase + { + private List _docs; + + public List Docs + { + get + { + return _docs; + } + set + { + __isset.@docs = true; + this._docs = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @docs; + } + + public EchoDocuments_args() + { + } + + public EchoDocuments_args DeepCopy() + { + var tmp140 = new EchoDocuments_args(); + if((Docs != null) && __isset.@docs) + { + tmp140.Docs = this.Docs.DeepCopy(); + } + tmp140.__isset.@docs = this.__isset.@docs; + return tmp140; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list141 = await iprot.ReadListBeginAsync(cancellationToken); + Docs = new List(_list141.Count); + for(int _i142 = 0; _i142 < _list141.Count; ++_i142) + { + global::Echo.ThriftModel.BusinessDocument _elem143; + _elem143 = new global::Echo.ThriftModel.BusinessDocument(); + await _elem143.ReadAsync(iprot, cancellationToken); + Docs.Add(_elem143); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp144 = new TStruct("EchoDocuments_args"); + await oprot.WriteStructBeginAsync(tmp144, cancellationToken); + var tmp145 = new TField(); + if((Docs != null) && __isset.@docs) + { + tmp145.Name = "docs"; + tmp145.Type = TType.List; + tmp145.ID = 1; + await oprot.WriteFieldBeginAsync(tmp145, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Docs.Count), cancellationToken); + foreach (global::Echo.ThriftModel.BusinessDocument _iter146 in Docs) + { + await _iter146.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoDocuments_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@docs == other.__isset.@docs) && ((!__isset.@docs) || (TCollections.Equals(Docs, other.Docs)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Docs != null) && __isset.@docs) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Docs); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp147 = new StringBuilder("EchoDocuments_args("); + int tmp148 = 0; + if((Docs != null) && __isset.@docs) + { + if(0 < tmp148++) { tmp147.Append(", "); } + tmp147.Append("Docs: "); + Docs.ToString(tmp147); + } + tmp147.Append(')'); + return tmp147.ToString(); + } + } + + + public partial class EchoDocuments_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoDocuments_result() + { + } + + public EchoDocuments_result DeepCopy() + { + var tmp149 = new EchoDocuments_result(); + if((Success != null) && __isset.@success) + { + tmp149.Success = this.Success.DeepCopy(); + } + tmp149.__isset.@success = this.__isset.@success; + return tmp149; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list150 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list150.Count); + for(int _i151 = 0; _i151 < _list150.Count; ++_i151) + { + global::Echo.ThriftModel.BusinessDocument _elem152; + _elem152 = new global::Echo.ThriftModel.BusinessDocument(); + await _elem152.ReadAsync(iprot, cancellationToken); + Success.Add(_elem152); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp153 = new TStruct("EchoDocuments_result"); + await oprot.WriteStructBeginAsync(tmp153, cancellationToken); + var tmp154 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp154.Name = "Success"; + tmp154.Type = TType.List; + tmp154.ID = 0; + await oprot.WriteFieldBeginAsync(tmp154, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Success.Count), cancellationToken); + foreach (global::Echo.ThriftModel.BusinessDocument _iter155 in Success) + { + await _iter155.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoDocuments_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp156 = new StringBuilder("EchoDocuments_result("); + int tmp157 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp157++) { tmp156.Append(", "); } + tmp156.Append("Success: "); + Success.ToString(tmp156); + } + tmp156.Append(')'); + return tmp156.ToString(); + } + } + + + public partial class EchoIntArray_args : TBase + { + private List _array; + + public List Array + { + get + { + return _array; + } + set + { + __isset.@array = true; + this._array = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @array; + } + + public EchoIntArray_args() + { + } + + public EchoIntArray_args DeepCopy() + { + var tmp158 = new EchoIntArray_args(); + if((Array != null) && __isset.@array) + { + tmp158.Array = this.Array.DeepCopy(); + } + tmp158.__isset.@array = this.__isset.@array; + return tmp158; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list159 = await iprot.ReadListBeginAsync(cancellationToken); + Array = new List(_list159.Count); + for(int _i160 = 0; _i160 < _list159.Count; ++_i160) + { + int _elem161; + _elem161 = await iprot.ReadI32Async(cancellationToken); + Array.Add(_elem161); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp162 = new TStruct("EchoIntArray_args"); + await oprot.WriteStructBeginAsync(tmp162, cancellationToken); + var tmp163 = new TField(); + if((Array != null) && __isset.@array) + { + tmp163.Name = "array"; + tmp163.Type = TType.List; + tmp163.ID = 1; + await oprot.WriteFieldBeginAsync(tmp163, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Array.Count), cancellationToken); + foreach (int _iter164 in Array) + { + await oprot.WriteI32Async(_iter164, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoIntArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@array == other.__isset.@array) && ((!__isset.@array) || (TCollections.Equals(Array, other.Array)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Array != null) && __isset.@array) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Array); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp165 = new StringBuilder("EchoIntArray_args("); + int tmp166 = 0; + if((Array != null) && __isset.@array) + { + if(0 < tmp166++) { tmp165.Append(", "); } + tmp165.Append("Array: "); + Array.ToString(tmp165); + } + tmp165.Append(')'); + return tmp165.ToString(); + } + } + + + public partial class EchoIntArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoIntArray_result() + { + } + + public EchoIntArray_result DeepCopy() + { + var tmp167 = new EchoIntArray_result(); + if((Success != null) && __isset.@success) + { + tmp167.Success = this.Success.DeepCopy(); + } + tmp167.__isset.@success = this.__isset.@success; + return tmp167; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list168 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list168.Count); + for(int _i169 = 0; _i169 < _list168.Count; ++_i169) + { + int _elem170; + _elem170 = await iprot.ReadI32Async(cancellationToken); + Success.Add(_elem170); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp171 = new TStruct("EchoIntArray_result"); + await oprot.WriteStructBeginAsync(tmp171, cancellationToken); + var tmp172 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp172.Name = "Success"; + tmp172.Type = TType.List; + tmp172.ID = 0; + await oprot.WriteFieldBeginAsync(tmp172, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Success.Count), cancellationToken); + foreach (int _iter173 in Success) + { + await oprot.WriteI32Async(_iter173, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoIntArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp174 = new StringBuilder("EchoIntArray_result("); + int tmp175 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp175++) { tmp174.Append(", "); } + tmp174.Append("Success: "); + Success.ToString(tmp174); + } + tmp174.Append(')'); + return tmp174.ToString(); + } + } + + + public partial class EchoStringArray_args : TBase + { + private List _array; + + public List Array + { + get + { + return _array; + } + set + { + __isset.@array = true; + this._array = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @array; + } + + public EchoStringArray_args() + { + } + + public EchoStringArray_args DeepCopy() + { + var tmp176 = new EchoStringArray_args(); + if((Array != null) && __isset.@array) + { + tmp176.Array = this.Array.DeepCopy(); + } + tmp176.__isset.@array = this.__isset.@array; + return tmp176; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list177 = await iprot.ReadListBeginAsync(cancellationToken); + Array = new List(_list177.Count); + for(int _i178 = 0; _i178 < _list177.Count; ++_i178) + { + string _elem179; + _elem179 = await iprot.ReadStringAsync(cancellationToken); + Array.Add(_elem179); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp180 = new TStruct("EchoStringArray_args"); + await oprot.WriteStructBeginAsync(tmp180, cancellationToken); + var tmp181 = new TField(); + if((Array != null) && __isset.@array) + { + tmp181.Name = "array"; + tmp181.Type = TType.List; + tmp181.ID = 1; + await oprot.WriteFieldBeginAsync(tmp181, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.String, Array.Count), cancellationToken); + foreach (string _iter182 in Array) + { + await oprot.WriteStringAsync(_iter182, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoStringArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@array == other.__isset.@array) && ((!__isset.@array) || (TCollections.Equals(Array, other.Array)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Array != null) && __isset.@array) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Array); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp183 = new StringBuilder("EchoStringArray_args("); + int tmp184 = 0; + if((Array != null) && __isset.@array) + { + if(0 < tmp184++) { tmp183.Append(", "); } + tmp183.Append("Array: "); + Array.ToString(tmp183); + } + tmp183.Append(')'); + return tmp183.ToString(); + } + } + + + public partial class EchoStringArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoStringArray_result() + { + } + + public EchoStringArray_result DeepCopy() + { + var tmp185 = new EchoStringArray_result(); + if((Success != null) && __isset.@success) + { + tmp185.Success = this.Success.DeepCopy(); + } + tmp185.__isset.@success = this.__isset.@success; + return tmp185; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list186 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list186.Count); + for(int _i187 = 0; _i187 < _list186.Count; ++_i187) + { + string _elem188; + _elem188 = await iprot.ReadStringAsync(cancellationToken); + Success.Add(_elem188); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp189 = new TStruct("EchoStringArray_result"); + await oprot.WriteStructBeginAsync(tmp189, cancellationToken); + var tmp190 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp190.Name = "Success"; + tmp190.Type = TType.List; + tmp190.ID = 0; + await oprot.WriteFieldBeginAsync(tmp190, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.String, Success.Count), cancellationToken); + foreach (string _iter191 in Success) + { + await oprot.WriteStringAsync(_iter191, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoStringArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp192 = new StringBuilder("EchoStringArray_result("); + int tmp193 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp193++) { tmp192.Append(", "); } + tmp192.Append("Success: "); + Success.ToString(tmp192); + } + tmp192.Append(')'); + return tmp192.ToString(); + } + } + + + public partial class EchoMap_args : TBase + { + private Dictionary _map; + + public Dictionary Map + { + get + { + return _map; + } + set + { + __isset.@map = true; + this._map = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @map; + } + + public EchoMap_args() + { + } + + public EchoMap_args DeepCopy() + { + var tmp194 = new EchoMap_args(); + if((Map != null) && __isset.@map) + { + tmp194.Map = this.Map.DeepCopy(); + } + tmp194.__isset.@map = this.__isset.@map; + return tmp194; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.Map) + { + { + var _map195 = await iprot.ReadMapBeginAsync(cancellationToken); + Map = new Dictionary(_map195.Count); + for(int _i196 = 0; _i196 < _map195.Count; ++_i196) + { + string _key197; + global::Echo.ThriftModel.BusinessDocument _val198; + _key197 = await iprot.ReadStringAsync(cancellationToken); + _val198 = new global::Echo.ThriftModel.BusinessDocument(); + await _val198.ReadAsync(iprot, cancellationToken); + Map[_key197] = _val198; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp199 = new TStruct("EchoMap_args"); + await oprot.WriteStructBeginAsync(tmp199, cancellationToken); + var tmp200 = new TField(); + if((Map != null) && __isset.@map) + { + tmp200.Name = "map"; + tmp200.Type = TType.Map; + tmp200.ID = 1; + await oprot.WriteFieldBeginAsync(tmp200, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Map.Count), cancellationToken); + foreach (string _iter201 in Map.Keys) + { + await oprot.WriteStringAsync(_iter201, cancellationToken); + await Map[_iter201].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoMap_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@map == other.__isset.@map) && ((!__isset.@map) || (TCollections.Equals(Map, other.Map)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Map != null) && __isset.@map) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Map); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp202 = new StringBuilder("EchoMap_args("); + int tmp203 = 0; + if((Map != null) && __isset.@map) + { + if(0 < tmp203++) { tmp202.Append(", "); } + tmp202.Append("Map: "); + Map.ToString(tmp202); + } + tmp202.Append(')'); + return tmp202.ToString(); + } + } + + + public partial class EchoMap_result : TBase + { + private Dictionary _success; + + public Dictionary Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoMap_result() + { + } + + public EchoMap_result DeepCopy() + { + var tmp204 = new EchoMap_result(); + if((Success != null) && __isset.@success) + { + tmp204.Success = this.Success.DeepCopy(); + } + tmp204.__isset.@success = this.__isset.@success; + return tmp204; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.Map) + { + { + var _map205 = await iprot.ReadMapBeginAsync(cancellationToken); + Success = new Dictionary(_map205.Count); + for(int _i206 = 0; _i206 < _map205.Count; ++_i206) + { + string _key207; + global::Echo.ThriftModel.BusinessDocument _val208; + _key207 = await iprot.ReadStringAsync(cancellationToken); + _val208 = new global::Echo.ThriftModel.BusinessDocument(); + await _val208.ReadAsync(iprot, cancellationToken); + Success[_key207] = _val208; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp209 = new TStruct("EchoMap_result"); + await oprot.WriteStructBeginAsync(tmp209, cancellationToken); + var tmp210 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp210.Name = "Success"; + tmp210.Type = TType.Map; + tmp210.ID = 0; + await oprot.WriteFieldBeginAsync(tmp210, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Success.Count), cancellationToken); + foreach (string _iter211 in Success.Keys) + { + await oprot.WriteStringAsync(_iter211, cancellationToken); + await Success[_iter211].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoMap_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp212 = new StringBuilder("EchoMap_result("); + int tmp213 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp213++) { tmp212.Append(", "); } + tmp212.Append("Success: "); + Success.ToString(tmp212); + } + tmp212.Append(')'); + return tmp212.ToString(); + } + } + + + public partial class EchoEnumArray_args : TBase + { + private List _docTypes; + + public List DocTypes + { + get + { + return _docTypes; + } + set + { + __isset.docTypes = true; + this._docTypes = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool docTypes; + } + + public EchoEnumArray_args() + { + } + + public EchoEnumArray_args DeepCopy() + { + var tmp214 = new EchoEnumArray_args(); + if((DocTypes != null) && __isset.docTypes) + { + tmp214.DocTypes = this.DocTypes.DeepCopy(); + } + tmp214.__isset.docTypes = this.__isset.docTypes; + return tmp214; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list215 = await iprot.ReadListBeginAsync(cancellationToken); + DocTypes = new List(_list215.Count); + for(int _i216 = 0; _i216 < _list215.Count; ++_i216) + { + global::Echo.ThriftModel.DocType _elem217; + _elem217 = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + DocTypes.Add(_elem217); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp218 = new TStruct("EchoEnumArray_args"); + await oprot.WriteStructBeginAsync(tmp218, cancellationToken); + var tmp219 = new TField(); + if((DocTypes != null) && __isset.docTypes) + { + tmp219.Name = "docTypes"; + tmp219.Type = TType.List; + tmp219.ID = 1; + await oprot.WriteFieldBeginAsync(tmp219, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, DocTypes.Count), cancellationToken); + foreach (global::Echo.ThriftModel.DocType _iter220 in DocTypes) + { + await oprot.WriteI32Async((int)_iter220, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoEnumArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.docTypes == other.__isset.docTypes) && ((!__isset.docTypes) || (TCollections.Equals(DocTypes, other.DocTypes)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((DocTypes != null) && __isset.docTypes) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(DocTypes); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp221 = new StringBuilder("EchoEnumArray_args("); + int tmp222 = 0; + if((DocTypes != null) && __isset.docTypes) + { + if(0 < tmp222++) { tmp221.Append(", "); } + tmp221.Append("DocTypes: "); + DocTypes.ToString(tmp221); + } + tmp221.Append(')'); + return tmp221.ToString(); + } + } + + + public partial class EchoEnumArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoEnumArray_result() + { + } + + public EchoEnumArray_result DeepCopy() + { + var tmp223 = new EchoEnumArray_result(); + if((Success != null) && __isset.@success) + { + tmp223.Success = this.Success.DeepCopy(); + } + tmp223.__isset.@success = this.__isset.@success; + return tmp223; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list224 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list224.Count); + for(int _i225 = 0; _i225 < _list224.Count; ++_i225) + { + global::Echo.ThriftModel.DocType _elem226; + _elem226 = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + Success.Add(_elem226); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp227 = new TStruct("EchoEnumArray_result"); + await oprot.WriteStructBeginAsync(tmp227, cancellationToken); + var tmp228 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp228.Name = "Success"; + tmp228.Type = TType.List; + tmp228.ID = 0; + await oprot.WriteFieldBeginAsync(tmp228, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Success.Count), cancellationToken); + foreach (global::Echo.ThriftModel.DocType _iter229 in Success) + { + await oprot.WriteI32Async((int)_iter229, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoEnumArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp230 = new StringBuilder("EchoEnumArray_result("); + int tmp231 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp231++) { tmp230.Append(", "); } + tmp230.Append("Success: "); + Success.ToString(tmp230); + } + tmp230.Append(')'); + return tmp230.ToString(); + } + } + + } + + } +} diff --git a/Tests/RPC/Client/Model/Thrift/ExtEntry.cs b/Tests/RPC/Client/Model/Thrift/ExtEntry.cs new file mode 100644 index 0000000..3922f80 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/ExtEntry.cs @@ -0,0 +1,229 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class ExtEntry : TBase + { + private string _key; + private global::Echo.ThriftModel.Variant _value; + + public string Key + { + get + { + return _key; + } + set + { + __isset.@key = true; + this._key = value; + } + } + + public global::Echo.ThriftModel.Variant Value + { + get + { + return _value; + } + set + { + __isset.@value = true; + this._value = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @key; + public bool @value; + } + + public ExtEntry() + { + } + + public ExtEntry DeepCopy() + { + var tmp10 = new ExtEntry(); + if((Key != null) && __isset.@key) + { + tmp10.Key = this.Key; + } + tmp10.__isset.@key = this.__isset.@key; + if((Value != null) && __isset.@value) + { + tmp10.Value = (global::Echo.ThriftModel.Variant)this.Value.DeepCopy(); + } + tmp10.__isset.@value = this.__isset.@value; + return tmp10; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Key = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Value = new global::Echo.ThriftModel.Variant(); + await Value.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp11 = new TStruct("ExtEntry"); + await oprot.WriteStructBeginAsync(tmp11, cancellationToken); + var tmp12 = new TField(); + if((Key != null) && __isset.@key) + { + tmp12.Name = "key"; + tmp12.Type = TType.String; + tmp12.ID = 1; + await oprot.WriteFieldBeginAsync(tmp12, cancellationToken); + await oprot.WriteStringAsync(Key, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Value != null) && __isset.@value) + { + tmp12.Name = "value"; + tmp12.Type = TType.Struct; + tmp12.ID = 2; + await oprot.WriteFieldBeginAsync(tmp12, cancellationToken); + await Value.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is ExtEntry other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@key == other.__isset.@key) && ((!__isset.@key) || (global::System.Object.Equals(Key, other.Key)))) + && ((__isset.@value == other.__isset.@value) && ((!__isset.@value) || (global::System.Object.Equals(Value, other.Value)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Key != null) && __isset.@key) + { + hashcode = (hashcode * 397) + Key.GetHashCode(); + } + if((Value != null) && __isset.@value) + { + hashcode = (hashcode * 397) + Value.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp13 = new StringBuilder("ExtEntry("); + int tmp14 = 0; + if((Key != null) && __isset.@key) + { + if(0 < tmp14++) { tmp13.Append(", "); } + tmp13.Append("Key: "); + Key.ToString(tmp13); + } + if((Value != null) && __isset.@value) + { + if(0 < tmp14++) { tmp13.Append(", "); } + tmp13.Append("Value: "); + Value.ToString(tmp13); + } + tmp13.Append(')'); + return tmp13.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/Kind.cs b/Tests/RPC/Client/Model/Thrift/Kind.cs new file mode 100644 index 0000000..34f7bed --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Kind.cs @@ -0,0 +1,30 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum Kind + { + @Null = 0, + @Bool = 1, + Int64 = 2, + UInt64 = 3, + @Double = 4, + @Decimal = 5, + @String = 6, + Bytes = 7, + DateTime = 8, + Guid = 9, + } +} diff --git a/Tests/RPC/Client/Model/Thrift/LineItem.cs b/Tests/RPC/Client/Model/Thrift/LineItem.cs new file mode 100644 index 0000000..13030bc --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/LineItem.cs @@ -0,0 +1,651 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class LineItem : TBase + { + private int _lineNo; + private global::Echo.ThriftModel.LineType _type; + private string _sku; + private string _description; + private double _qty; + private string _qtyUnit; + private double _unitPrice; + private double _vatRate; + private double _discount; + private Dictionary _ext; + + public int LineNo + { + get + { + return _lineNo; + } + set + { + __isset.lineNo = true; + this._lineNo = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.LineType Type + { + get + { + return _type; + } + set + { + __isset.@type = true; + this._type = value; + } + } + + public string Sku + { + get + { + return _sku; + } + set + { + __isset.@sku = true; + this._sku = value; + } + } + + public string Description + { + get + { + return _description; + } + set + { + __isset.@description = true; + this._description = value; + } + } + + public double Qty + { + get + { + return _qty; + } + set + { + __isset.@qty = true; + this._qty = value; + } + } + + public string QtyUnit + { + get + { + return _qtyUnit; + } + set + { + __isset.qtyUnit = true; + this._qtyUnit = value; + } + } + + public double UnitPrice + { + get + { + return _unitPrice; + } + set + { + __isset.unitPrice = true; + this._unitPrice = value; + } + } + + public double VatRate + { + get + { + return _vatRate; + } + set + { + __isset.vatRate = true; + this._vatRate = value; + } + } + + public double Discount + { + get + { + return _discount; + } + set + { + __isset.@discount = true; + this._discount = value; + } + } + + public Dictionary Ext + { + get + { + return _ext; + } + set + { + __isset.@ext = true; + this._ext = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool lineNo; + public bool @type; + public bool @sku; + public bool @description; + public bool @qty; + public bool qtyUnit; + public bool unitPrice; + public bool vatRate; + public bool @discount; + public bool @ext; + } + + public LineItem() + { + } + + public LineItem DeepCopy() + { + var tmp35 = new LineItem(); + if(__isset.lineNo) + { + tmp35.LineNo = this.LineNo; + } + tmp35.__isset.lineNo = this.__isset.lineNo; + if(__isset.@type) + { + tmp35.Type = this.Type; + } + tmp35.__isset.@type = this.__isset.@type; + if((Sku != null) && __isset.@sku) + { + tmp35.Sku = this.Sku; + } + tmp35.__isset.@sku = this.__isset.@sku; + if((Description != null) && __isset.@description) + { + tmp35.Description = this.Description; + } + tmp35.__isset.@description = this.__isset.@description; + if(__isset.@qty) + { + tmp35.Qty = this.Qty; + } + tmp35.__isset.@qty = this.__isset.@qty; + if((QtyUnit != null) && __isset.qtyUnit) + { + tmp35.QtyUnit = this.QtyUnit; + } + tmp35.__isset.qtyUnit = this.__isset.qtyUnit; + if(__isset.unitPrice) + { + tmp35.UnitPrice = this.UnitPrice; + } + tmp35.__isset.unitPrice = this.__isset.unitPrice; + if(__isset.vatRate) + { + tmp35.VatRate = this.VatRate; + } + tmp35.__isset.vatRate = this.__isset.vatRate; + if(__isset.@discount) + { + tmp35.Discount = this.Discount; + } + tmp35.__isset.@discount = this.__isset.@discount; + if((Ext != null) && __isset.@ext) + { + tmp35.Ext = this.Ext.DeepCopy(); + } + tmp35.__isset.@ext = this.__isset.@ext; + return tmp35; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + LineNo = await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.I32) + { + Type = (global::Echo.ThriftModel.LineType)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Sku = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Description = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + Qty = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + QtyUnit = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.Double) + { + UnitPrice = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.Double) + { + VatRate = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 9: + if (field.Type == TType.Double) + { + Discount = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 10: + if (field.Type == TType.Map) + { + { + var _map36 = await iprot.ReadMapBeginAsync(cancellationToken); + Ext = new Dictionary(_map36.Count); + for(int _i37 = 0; _i37 < _map36.Count; ++_i37) + { + string _key38; + global::Echo.ThriftModel.Variant _val39; + _key38 = await iprot.ReadStringAsync(cancellationToken); + _val39 = new global::Echo.ThriftModel.Variant(); + await _val39.ReadAsync(iprot, cancellationToken); + Ext[_key38] = _val39; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp40 = new TStruct("LineItem"); + await oprot.WriteStructBeginAsync(tmp40, cancellationToken); + var tmp41 = new TField(); + if(__isset.lineNo) + { + tmp41.Name = "lineNo"; + tmp41.Type = TType.I32; + tmp41.ID = 1; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteI32Async(LineNo, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@type) + { + tmp41.Name = "type"; + tmp41.Type = TType.I32; + tmp41.ID = 2; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteI32Async((int)Type, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Sku != null) && __isset.@sku) + { + tmp41.Name = "sku"; + tmp41.Type = TType.String; + tmp41.ID = 3; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(Sku, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Description != null) && __isset.@description) + { + tmp41.Name = "description"; + tmp41.Type = TType.String; + tmp41.ID = 4; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(Description, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@qty) + { + tmp41.Name = "qty"; + tmp41.Type = TType.Double; + tmp41.ID = 5; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(Qty, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + tmp41.Name = "qtyUnit"; + tmp41.Type = TType.String; + tmp41.ID = 6; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(QtyUnit, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.unitPrice) + { + tmp41.Name = "unitPrice"; + tmp41.Type = TType.Double; + tmp41.ID = 7; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(UnitPrice, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.vatRate) + { + tmp41.Name = "vatRate"; + tmp41.Type = TType.Double; + tmp41.ID = 8; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(VatRate, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@discount) + { + tmp41.Name = "discount"; + tmp41.Type = TType.Double; + tmp41.ID = 9; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(Discount, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Ext != null) && __isset.@ext) + { + tmp41.Name = "ext"; + tmp41.Type = TType.Map; + tmp41.ID = 10; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Ext.Count), cancellationToken); + foreach (string _iter42 in Ext.Keys) + { + await oprot.WriteStringAsync(_iter42, cancellationToken); + await Ext[_iter42].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is LineItem other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.lineNo == other.__isset.lineNo) && ((!__isset.lineNo) || (global::System.Object.Equals(LineNo, other.LineNo)))) + && ((__isset.@type == other.__isset.@type) && ((!__isset.@type) || (global::System.Object.Equals(Type, other.Type)))) + && ((__isset.@sku == other.__isset.@sku) && ((!__isset.@sku) || (global::System.Object.Equals(Sku, other.Sku)))) + && ((__isset.@description == other.__isset.@description) && ((!__isset.@description) || (global::System.Object.Equals(Description, other.Description)))) + && ((__isset.@qty == other.__isset.@qty) && ((!__isset.@qty) || (global::System.Object.Equals(Qty, other.Qty)))) + && ((__isset.qtyUnit == other.__isset.qtyUnit) && ((!__isset.qtyUnit) || (global::System.Object.Equals(QtyUnit, other.QtyUnit)))) + && ((__isset.unitPrice == other.__isset.unitPrice) && ((!__isset.unitPrice) || (global::System.Object.Equals(UnitPrice, other.UnitPrice)))) + && ((__isset.vatRate == other.__isset.vatRate) && ((!__isset.vatRate) || (global::System.Object.Equals(VatRate, other.VatRate)))) + && ((__isset.@discount == other.__isset.@discount) && ((!__isset.@discount) || (global::System.Object.Equals(Discount, other.Discount)))) + && ((__isset.@ext == other.__isset.@ext) && ((!__isset.@ext) || (TCollections.Equals(Ext, other.Ext)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.lineNo) + { + hashcode = (hashcode * 397) + LineNo.GetHashCode(); + } + if(__isset.@type) + { + hashcode = (hashcode * 397) + Type.GetHashCode(); + } + if((Sku != null) && __isset.@sku) + { + hashcode = (hashcode * 397) + Sku.GetHashCode(); + } + if((Description != null) && __isset.@description) + { + hashcode = (hashcode * 397) + Description.GetHashCode(); + } + if(__isset.@qty) + { + hashcode = (hashcode * 397) + Qty.GetHashCode(); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + hashcode = (hashcode * 397) + QtyUnit.GetHashCode(); + } + if(__isset.unitPrice) + { + hashcode = (hashcode * 397) + UnitPrice.GetHashCode(); + } + if(__isset.vatRate) + { + hashcode = (hashcode * 397) + VatRate.GetHashCode(); + } + if(__isset.@discount) + { + hashcode = (hashcode * 397) + Discount.GetHashCode(); + } + if((Ext != null) && __isset.@ext) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Ext); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp43 = new StringBuilder("LineItem("); + int tmp44 = 0; + if(__isset.lineNo) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("LineNo: "); + LineNo.ToString(tmp43); + } + if(__isset.@type) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Type: "); + Type.ToString(tmp43); + } + if((Sku != null) && __isset.@sku) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Sku: "); + Sku.ToString(tmp43); + } + if((Description != null) && __isset.@description) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Description: "); + Description.ToString(tmp43); + } + if(__isset.@qty) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Qty: "); + Qty.ToString(tmp43); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("QtyUnit: "); + QtyUnit.ToString(tmp43); + } + if(__isset.unitPrice) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("UnitPrice: "); + UnitPrice.ToString(tmp43); + } + if(__isset.vatRate) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("VatRate: "); + VatRate.ToString(tmp43); + } + if(__isset.@discount) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Discount: "); + Discount.ToString(tmp43); + } + if((Ext != null) && __isset.@ext) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Ext: "); + Ext.ToString(tmp43); + } + tmp43.Append(')'); + return tmp43.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/LineType.cs b/Tests/RPC/Client/Model/Thrift/LineType.cs new file mode 100644 index 0000000..83fe925 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/LineType.cs @@ -0,0 +1,24 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum LineType + { + Product = 0, + Service = 1, + Discount = 2, + Shipping = 3, + } +} diff --git a/Tests/RPC/Client/Model/Thrift/MetaEntry.cs b/Tests/RPC/Client/Model/Thrift/MetaEntry.cs new file mode 100644 index 0000000..7cc77a0 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/MetaEntry.cs @@ -0,0 +1,229 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class MetaEntry : TBase + { + private string _key; + private global::Echo.ThriftModel.Variant _value; + + public string Key + { + get + { + return _key; + } + set + { + __isset.@key = true; + this._key = value; + } + } + + public global::Echo.ThriftModel.Variant Value + { + get + { + return _value; + } + set + { + __isset.@value = true; + this._value = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @key; + public bool @value; + } + + public MetaEntry() + { + } + + public MetaEntry DeepCopy() + { + var tmp5 = new MetaEntry(); + if((Key != null) && __isset.@key) + { + tmp5.Key = this.Key; + } + tmp5.__isset.@key = this.__isset.@key; + if((Value != null) && __isset.@value) + { + tmp5.Value = (global::Echo.ThriftModel.Variant)this.Value.DeepCopy(); + } + tmp5.__isset.@value = this.__isset.@value; + return tmp5; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Key = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Value = new global::Echo.ThriftModel.Variant(); + await Value.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp6 = new TStruct("MetaEntry"); + await oprot.WriteStructBeginAsync(tmp6, cancellationToken); + var tmp7 = new TField(); + if((Key != null) && __isset.@key) + { + tmp7.Name = "key"; + tmp7.Type = TType.String; + tmp7.ID = 1; + await oprot.WriteFieldBeginAsync(tmp7, cancellationToken); + await oprot.WriteStringAsync(Key, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Value != null) && __isset.@value) + { + tmp7.Name = "value"; + tmp7.Type = TType.Struct; + tmp7.ID = 2; + await oprot.WriteFieldBeginAsync(tmp7, cancellationToken); + await Value.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is MetaEntry other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@key == other.__isset.@key) && ((!__isset.@key) || (global::System.Object.Equals(Key, other.Key)))) + && ((__isset.@value == other.__isset.@value) && ((!__isset.@value) || (global::System.Object.Equals(Value, other.Value)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Key != null) && __isset.@key) + { + hashcode = (hashcode * 397) + Key.GetHashCode(); + } + if((Value != null) && __isset.@value) + { + hashcode = (hashcode * 397) + Value.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp8 = new StringBuilder("MetaEntry("); + int tmp9 = 0; + if((Key != null) && __isset.@key) + { + if(0 < tmp9++) { tmp8.Append(", "); } + tmp8.Append("Key: "); + Key.ToString(tmp8); + } + if((Value != null) && __isset.@value) + { + if(0 < tmp9++) { tmp8.Append(", "); } + tmp8.Append("Value: "); + Value.ToString(tmp8); + } + tmp8.Append(')'); + return tmp8.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/Party.cs b/Tests/RPC/Client/Model/Thrift/Party.cs new file mode 100644 index 0000000..42bb371 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Party.cs @@ -0,0 +1,479 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Party : TBase + { + private long _id; + private string _name; + private string _taxId; + private string _email; + private string _phone; + private global::Echo.ThriftModel.Address _address; + private string _preferredLanguage; + + public long Id + { + get + { + return _id; + } + set + { + __isset.@id = true; + this._id = value; + } + } + + public string Name + { + get + { + return _name; + } + set + { + __isset.@name = true; + this._name = value; + } + } + + public string TaxId + { + get + { + return _taxId; + } + set + { + __isset.taxId = true; + this._taxId = value; + } + } + + public string Email + { + get + { + return _email; + } + set + { + __isset.@email = true; + this._email = value; + } + } + + public string Phone + { + get + { + return _phone; + } + set + { + __isset.@phone = true; + this._phone = value; + } + } + + public global::Echo.ThriftModel.Address Address + { + get + { + return _address; + } + set + { + __isset.@address = true; + this._address = value; + } + } + + public string PreferredLanguage + { + get + { + return _preferredLanguage; + } + set + { + __isset.preferredLanguage = true; + this._preferredLanguage = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @id; + public bool @name; + public bool taxId; + public bool @email; + public bool @phone; + public bool @address; + public bool preferredLanguage; + } + + public Party() + { + } + + public Party DeepCopy() + { + var tmp20 = new Party(); + if(__isset.@id) + { + tmp20.Id = this.Id; + } + tmp20.__isset.@id = this.__isset.@id; + if((Name != null) && __isset.@name) + { + tmp20.Name = this.Name; + } + tmp20.__isset.@name = this.__isset.@name; + if((TaxId != null) && __isset.taxId) + { + tmp20.TaxId = this.TaxId; + } + tmp20.__isset.taxId = this.__isset.taxId; + if((Email != null) && __isset.@email) + { + tmp20.Email = this.Email; + } + tmp20.__isset.@email = this.__isset.@email; + if((Phone != null) && __isset.@phone) + { + tmp20.Phone = this.Phone; + } + tmp20.__isset.@phone = this.__isset.@phone; + if((Address != null) && __isset.@address) + { + tmp20.Address = (global::Echo.ThriftModel.Address)this.Address.DeepCopy(); + } + tmp20.__isset.@address = this.__isset.@address; + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + tmp20.PreferredLanguage = this.PreferredLanguage; + } + tmp20.__isset.preferredLanguage = this.__isset.preferredLanguage; + return tmp20; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I64) + { + Id = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + Name = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + TaxId = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Email = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.String) + { + Phone = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.Struct) + { + Address = new global::Echo.ThriftModel.Address(); + await Address.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + PreferredLanguage = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp21 = new TStruct("Party"); + await oprot.WriteStructBeginAsync(tmp21, cancellationToken); + var tmp22 = new TField(); + if(__isset.@id) + { + tmp22.Name = "id"; + tmp22.Type = TType.I64; + tmp22.ID = 1; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteI64Async(Id, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Name != null) && __isset.@name) + { + tmp22.Name = "name"; + tmp22.Type = TType.String; + tmp22.ID = 2; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Name, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((TaxId != null) && __isset.taxId) + { + tmp22.Name = "taxId"; + tmp22.Type = TType.String; + tmp22.ID = 3; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(TaxId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Email != null) && __isset.@email) + { + tmp22.Name = "email"; + tmp22.Type = TType.String; + tmp22.ID = 4; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Email, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Phone != null) && __isset.@phone) + { + tmp22.Name = "phone"; + tmp22.Type = TType.String; + tmp22.ID = 5; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Phone, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Address != null) && __isset.@address) + { + tmp22.Name = "address"; + tmp22.Type = TType.Struct; + tmp22.ID = 6; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await Address.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + tmp22.Name = "preferredLanguage"; + tmp22.Type = TType.String; + tmp22.ID = 7; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(PreferredLanguage, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Party other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@id == other.__isset.@id) && ((!__isset.@id) || (global::System.Object.Equals(Id, other.Id)))) + && ((__isset.@name == other.__isset.@name) && ((!__isset.@name) || (global::System.Object.Equals(Name, other.Name)))) + && ((__isset.taxId == other.__isset.taxId) && ((!__isset.taxId) || (global::System.Object.Equals(TaxId, other.TaxId)))) + && ((__isset.@email == other.__isset.@email) && ((!__isset.@email) || (global::System.Object.Equals(Email, other.Email)))) + && ((__isset.@phone == other.__isset.@phone) && ((!__isset.@phone) || (global::System.Object.Equals(Phone, other.Phone)))) + && ((__isset.@address == other.__isset.@address) && ((!__isset.@address) || (global::System.Object.Equals(Address, other.Address)))) + && ((__isset.preferredLanguage == other.__isset.preferredLanguage) && ((!__isset.preferredLanguage) || (global::System.Object.Equals(PreferredLanguage, other.PreferredLanguage)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@id) + { + hashcode = (hashcode * 397) + Id.GetHashCode(); + } + if((Name != null) && __isset.@name) + { + hashcode = (hashcode * 397) + Name.GetHashCode(); + } + if((TaxId != null) && __isset.taxId) + { + hashcode = (hashcode * 397) + TaxId.GetHashCode(); + } + if((Email != null) && __isset.@email) + { + hashcode = (hashcode * 397) + Email.GetHashCode(); + } + if((Phone != null) && __isset.@phone) + { + hashcode = (hashcode * 397) + Phone.GetHashCode(); + } + if((Address != null) && __isset.@address) + { + hashcode = (hashcode * 397) + Address.GetHashCode(); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + hashcode = (hashcode * 397) + PreferredLanguage.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp23 = new StringBuilder("Party("); + int tmp24 = 0; + if(__isset.@id) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Id: "); + Id.ToString(tmp23); + } + if((Name != null) && __isset.@name) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Name: "); + Name.ToString(tmp23); + } + if((TaxId != null) && __isset.taxId) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("TaxId: "); + TaxId.ToString(tmp23); + } + if((Email != null) && __isset.@email) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Email: "); + Email.ToString(tmp23); + } + if((Phone != null) && __isset.@phone) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Phone: "); + Phone.ToString(tmp23); + } + if((Address != null) && __isset.@address) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Address: "); + Address.ToString(tmp23); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("PreferredLanguage: "); + PreferredLanguage.ToString(tmp23); + } + tmp23.Append(')'); + return tmp23.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/Payment.cs b/Tests/RPC/Client/Model/Thrift/Payment.cs new file mode 100644 index 0000000..36ccf56 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Payment.cs @@ -0,0 +1,436 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Payment : TBase + { + private global::Echo.ThriftModel.PaymentMethod _method; + private double _amount; + private string _reference; + private long _timestamp; + private double _fee; + private global::Echo.ThriftModel.Currency _currency; + + /// + /// + /// + /// + public global::Echo.ThriftModel.PaymentMethod Method + { + get + { + return _method; + } + set + { + __isset.@method = true; + this._method = value; + } + } + + public double Amount + { + get + { + return _amount; + } + set + { + __isset.@amount = true; + this._amount = value; + } + } + + public string Reference + { + get + { + return _reference; + } + set + { + __isset.@reference = true; + this._reference = value; + } + } + + public long Timestamp + { + get + { + return _timestamp; + } + set + { + __isset.@timestamp = true; + this._timestamp = value; + } + } + + public double Fee + { + get + { + return _fee; + } + set + { + __isset.@fee = true; + this._fee = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.Currency Currency + { + get + { + return _currency; + } + set + { + __isset.@currency = true; + this._currency = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @method; + public bool @amount; + public bool @reference; + public bool @timestamp; + public bool @fee; + public bool @currency; + } + + public Payment() + { + } + + public Payment DeepCopy() + { + var tmp45 = new Payment(); + if(__isset.@method) + { + tmp45.Method = this.Method; + } + tmp45.__isset.@method = this.__isset.@method; + if(__isset.@amount) + { + tmp45.Amount = this.Amount; + } + tmp45.__isset.@amount = this.__isset.@amount; + if((Reference != null) && __isset.@reference) + { + tmp45.Reference = this.Reference; + } + tmp45.__isset.@reference = this.__isset.@reference; + if(__isset.@timestamp) + { + tmp45.Timestamp = this.Timestamp; + } + tmp45.__isset.@timestamp = this.__isset.@timestamp; + if(__isset.@fee) + { + tmp45.Fee = this.Fee; + } + tmp45.__isset.@fee = this.__isset.@fee; + if(__isset.@currency) + { + tmp45.Currency = this.Currency; + } + tmp45.__isset.@currency = this.__isset.@currency; + return tmp45; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + Method = (global::Echo.ThriftModel.PaymentMethod)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Double) + { + Amount = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Reference = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + Timestamp = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + Fee = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.I32) + { + Currency = (global::Echo.ThriftModel.Currency)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp46 = new TStruct("Payment"); + await oprot.WriteStructBeginAsync(tmp46, cancellationToken); + var tmp47 = new TField(); + if(__isset.@method) + { + tmp47.Name = "method"; + tmp47.Type = TType.I32; + tmp47.ID = 1; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI32Async((int)Method, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@amount) + { + tmp47.Name = "amount"; + tmp47.Type = TType.Double; + tmp47.ID = 2; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteDoubleAsync(Amount, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Reference != null) && __isset.@reference) + { + tmp47.Name = "reference"; + tmp47.Type = TType.String; + tmp47.ID = 3; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteStringAsync(Reference, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@timestamp) + { + tmp47.Name = "timestamp"; + tmp47.Type = TType.I64; + tmp47.ID = 4; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI64Async(Timestamp, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@fee) + { + tmp47.Name = "fee"; + tmp47.Type = TType.Double; + tmp47.ID = 5; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteDoubleAsync(Fee, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@currency) + { + tmp47.Name = "currency"; + tmp47.Type = TType.I32; + tmp47.ID = 6; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI32Async((int)Currency, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Payment other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@method == other.__isset.@method) && ((!__isset.@method) || (global::System.Object.Equals(Method, other.Method)))) + && ((__isset.@amount == other.__isset.@amount) && ((!__isset.@amount) || (global::System.Object.Equals(Amount, other.Amount)))) + && ((__isset.@reference == other.__isset.@reference) && ((!__isset.@reference) || (global::System.Object.Equals(Reference, other.Reference)))) + && ((__isset.@timestamp == other.__isset.@timestamp) && ((!__isset.@timestamp) || (global::System.Object.Equals(Timestamp, other.Timestamp)))) + && ((__isset.@fee == other.__isset.@fee) && ((!__isset.@fee) || (global::System.Object.Equals(Fee, other.Fee)))) + && ((__isset.@currency == other.__isset.@currency) && ((!__isset.@currency) || (global::System.Object.Equals(Currency, other.Currency)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@method) + { + hashcode = (hashcode * 397) + Method.GetHashCode(); + } + if(__isset.@amount) + { + hashcode = (hashcode * 397) + Amount.GetHashCode(); + } + if((Reference != null) && __isset.@reference) + { + hashcode = (hashcode * 397) + Reference.GetHashCode(); + } + if(__isset.@timestamp) + { + hashcode = (hashcode * 397) + Timestamp.GetHashCode(); + } + if(__isset.@fee) + { + hashcode = (hashcode * 397) + Fee.GetHashCode(); + } + if(__isset.@currency) + { + hashcode = (hashcode * 397) + Currency.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp48 = new StringBuilder("Payment("); + int tmp49 = 0; + if(__isset.@method) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Method: "); + Method.ToString(tmp48); + } + if(__isset.@amount) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Amount: "); + Amount.ToString(tmp48); + } + if((Reference != null) && __isset.@reference) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Reference: "); + Reference.ToString(tmp48); + } + if(__isset.@timestamp) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Timestamp: "); + Timestamp.ToString(tmp48); + } + if(__isset.@fee) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Fee: "); + Fee.ToString(tmp48); + } + if(__isset.@currency) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Currency: "); + Currency.ToString(tmp48); + } + tmp48.Append(')'); + return tmp48.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/PaymentMethod.cs b/Tests/RPC/Client/Model/Thrift/PaymentMethod.cs new file mode 100644 index 0000000..f1cdc92 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/PaymentMethod.cs @@ -0,0 +1,25 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum PaymentMethod + { + Cash = 0, + Card = 1, + Wire = 2, + Crypto = 3, + Other = 4, + } +} diff --git a/Tests/RPC/Client/Model/Thrift/Variant.cs b/Tests/RPC/Client/Model/Thrift/Variant.cs new file mode 100644 index 0000000..935f322 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/Variant.cs @@ -0,0 +1,582 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Variant : TBase + { + private global::Echo.ThriftModel.Kind _tag; + private bool _boolVal; + private long _i64Val; + private long _u64Val; + private double _f64Val; + private string _strVal; + private byte[] _bytesVal; + private long _dtVal; + private byte[] _guidVal; + + /// + /// + /// + /// + public global::Echo.ThriftModel.Kind Tag + { + get + { + return _tag; + } + set + { + __isset.@tag = true; + this._tag = value; + } + } + + public bool BoolVal + { + get + { + return _boolVal; + } + set + { + __isset.boolVal = true; + this._boolVal = value; + } + } + + public long I64Val + { + get + { + return _i64Val; + } + set + { + __isset.i64Val = true; + this._i64Val = value; + } + } + + public long U64Val + { + get + { + return _u64Val; + } + set + { + __isset.u64Val = true; + this._u64Val = value; + } + } + + public double F64Val + { + get + { + return _f64Val; + } + set + { + __isset.f64Val = true; + this._f64Val = value; + } + } + + public string StrVal + { + get + { + return _strVal; + } + set + { + __isset.strVal = true; + this._strVal = value; + } + } + + public byte[] BytesVal + { + get + { + return _bytesVal; + } + set + { + __isset.bytesVal = true; + this._bytesVal = value; + } + } + + public long DtVal + { + get + { + return _dtVal; + } + set + { + __isset.dtVal = true; + this._dtVal = value; + } + } + + public byte[] GuidVal + { + get + { + return _guidVal; + } + set + { + __isset.guidVal = true; + this._guidVal = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @tag; + public bool boolVal; + public bool i64Val; + public bool u64Val; + public bool f64Val; + public bool strVal; + public bool bytesVal; + public bool dtVal; + public bool guidVal; + } + + public Variant() + { + } + + public Variant DeepCopy() + { + var tmp0 = new Variant(); + if(__isset.@tag) + { + tmp0.Tag = this.Tag; + } + tmp0.__isset.@tag = this.__isset.@tag; + if(__isset.boolVal) + { + tmp0.BoolVal = this.BoolVal; + } + tmp0.__isset.boolVal = this.__isset.boolVal; + if(__isset.i64Val) + { + tmp0.I64Val = this.I64Val; + } + tmp0.__isset.i64Val = this.__isset.i64Val; + if(__isset.u64Val) + { + tmp0.U64Val = this.U64Val; + } + tmp0.__isset.u64Val = this.__isset.u64Val; + if(__isset.f64Val) + { + tmp0.F64Val = this.F64Val; + } + tmp0.__isset.f64Val = this.__isset.f64Val; + if((StrVal != null) && __isset.strVal) + { + tmp0.StrVal = this.StrVal; + } + tmp0.__isset.strVal = this.__isset.strVal; + if((BytesVal != null) && __isset.bytesVal) + { + tmp0.BytesVal = this.BytesVal.ToArray(); + } + tmp0.__isset.bytesVal = this.__isset.bytesVal; + if(__isset.dtVal) + { + tmp0.DtVal = this.DtVal; + } + tmp0.__isset.dtVal = this.__isset.dtVal; + if((GuidVal != null) && __isset.guidVal) + { + tmp0.GuidVal = this.GuidVal.ToArray(); + } + tmp0.__isset.guidVal = this.__isset.guidVal; + return tmp0; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + Tag = (global::Echo.ThriftModel.Kind)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Bool) + { + BoolVal = await iprot.ReadBoolAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.I64) + { + I64Val = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + U64Val = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + F64Val = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + StrVal = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + BytesVal = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.I64) + { + DtVal = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 9: + if (field.Type == TType.String) + { + GuidVal = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp1 = new TStruct("Variant"); + await oprot.WriteStructBeginAsync(tmp1, cancellationToken); + var tmp2 = new TField(); + if(__isset.@tag) + { + tmp2.Name = "tag"; + tmp2.Type = TType.I32; + tmp2.ID = 1; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI32Async((int)Tag, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.boolVal) + { + tmp2.Name = "boolVal"; + tmp2.Type = TType.Bool; + tmp2.ID = 2; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBoolAsync(BoolVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.i64Val) + { + tmp2.Name = "i64Val"; + tmp2.Type = TType.I64; + tmp2.ID = 3; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(I64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.u64Val) + { + tmp2.Name = "u64Val"; + tmp2.Type = TType.I64; + tmp2.ID = 4; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(U64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.f64Val) + { + tmp2.Name = "f64Val"; + tmp2.Type = TType.Double; + tmp2.ID = 5; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteDoubleAsync(F64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((StrVal != null) && __isset.strVal) + { + tmp2.Name = "strVal"; + tmp2.Type = TType.String; + tmp2.ID = 6; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteStringAsync(StrVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((BytesVal != null) && __isset.bytesVal) + { + tmp2.Name = "bytesVal"; + tmp2.Type = TType.String; + tmp2.ID = 7; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBinaryAsync(BytesVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.dtVal) + { + tmp2.Name = "dtVal"; + tmp2.Type = TType.I64; + tmp2.ID = 8; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(DtVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((GuidVal != null) && __isset.guidVal) + { + tmp2.Name = "guidVal"; + tmp2.Type = TType.String; + tmp2.ID = 9; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBinaryAsync(GuidVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Variant other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@tag == other.__isset.@tag) && ((!__isset.@tag) || (global::System.Object.Equals(Tag, other.Tag)))) + && ((__isset.boolVal == other.__isset.boolVal) && ((!__isset.boolVal) || (global::System.Object.Equals(BoolVal, other.BoolVal)))) + && ((__isset.i64Val == other.__isset.i64Val) && ((!__isset.i64Val) || (global::System.Object.Equals(I64Val, other.I64Val)))) + && ((__isset.u64Val == other.__isset.u64Val) && ((!__isset.u64Val) || (global::System.Object.Equals(U64Val, other.U64Val)))) + && ((__isset.f64Val == other.__isset.f64Val) && ((!__isset.f64Val) || (global::System.Object.Equals(F64Val, other.F64Val)))) + && ((__isset.strVal == other.__isset.strVal) && ((!__isset.strVal) || (global::System.Object.Equals(StrVal, other.StrVal)))) + && ((__isset.bytesVal == other.__isset.bytesVal) && ((!__isset.bytesVal) || (TCollections.Equals(BytesVal, other.BytesVal)))) + && ((__isset.dtVal == other.__isset.dtVal) && ((!__isset.dtVal) || (global::System.Object.Equals(DtVal, other.DtVal)))) + && ((__isset.guidVal == other.__isset.guidVal) && ((!__isset.guidVal) || (TCollections.Equals(GuidVal, other.GuidVal)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@tag) + { + hashcode = (hashcode * 397) + Tag.GetHashCode(); + } + if(__isset.boolVal) + { + hashcode = (hashcode * 397) + BoolVal.GetHashCode(); + } + if(__isset.i64Val) + { + hashcode = (hashcode * 397) + I64Val.GetHashCode(); + } + if(__isset.u64Val) + { + hashcode = (hashcode * 397) + U64Val.GetHashCode(); + } + if(__isset.f64Val) + { + hashcode = (hashcode * 397) + F64Val.GetHashCode(); + } + if((StrVal != null) && __isset.strVal) + { + hashcode = (hashcode * 397) + StrVal.GetHashCode(); + } + if((BytesVal != null) && __isset.bytesVal) + { + hashcode = (hashcode * 397) + BytesVal.GetHashCode(); + } + if(__isset.dtVal) + { + hashcode = (hashcode * 397) + DtVal.GetHashCode(); + } + if((GuidVal != null) && __isset.guidVal) + { + hashcode = (hashcode * 397) + GuidVal.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp3 = new StringBuilder("Variant("); + int tmp4 = 0; + if(__isset.@tag) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("Tag: "); + Tag.ToString(tmp3); + } + if(__isset.boolVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("BoolVal: "); + BoolVal.ToString(tmp3); + } + if(__isset.i64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("I64Val: "); + I64Val.ToString(tmp3); + } + if(__isset.u64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("U64Val: "); + U64Val.ToString(tmp3); + } + if(__isset.f64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("F64Val: "); + F64Val.ToString(tmp3); + } + if((StrVal != null) && __isset.strVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("StrVal: "); + StrVal.ToString(tmp3); + } + if((BytesVal != null) && __isset.bytesVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("BytesVal: "); + BytesVal.ToString(tmp3); + } + if(__isset.dtVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("DtVal: "); + DtVal.ToString(tmp3); + } + if((GuidVal != null) && __isset.guidVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("GuidVal: "); + GuidVal.ToString(tmp3); + } + tmp3.Append(')'); + return tmp3.ToString(); + } + } + +} diff --git a/Tests/RPC/Client/Model/Thrift/echo.Extensions.cs b/Tests/RPC/Client/Model/Thrift/echo.Extensions.cs new file mode 100644 index 0000000..4d5aed8 --- /dev/null +++ b/Tests/RPC/Client/Model/Thrift/echo.Extensions.cs @@ -0,0 +1,276 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public static class echoExtensions + { + public static bool Equals(this Dictionary instance, object that) + { + if (!(that is Dictionary other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this Dictionary instance) + { + return TCollections.GetHashCode(instance); + } + + + public static Dictionary DeepCopy(this Dictionary source) + { + if (source == null) + return null; + + var tmp232 = new Dictionary(source.Count); + foreach (var pair in source) + tmp232.Add((pair.Key != null) ? pair.Key : null, (pair.Value != null) ? pair.Value.DeepCopy() : null); + return tmp232; + } + + + public static bool Equals(this Dictionary instance, object that) + { + if (!(that is Dictionary other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this Dictionary instance) + { + return TCollections.GetHashCode(instance); + } + + + public static Dictionary DeepCopy(this Dictionary source) + { + if (source == null) + return null; + + var tmp233 = new Dictionary(source.Count); + foreach (var pair in source) + tmp233.Add((pair.Key != null) ? pair.Key : null, (pair.Value != null) ? pair.Value.DeepCopy() : null); + return tmp233; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp234 = new List(source.Count); + foreach (var elem in source) + tmp234.Add((elem != null) ? elem.DeepCopy() : null); + return tmp234; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp235 = new List(source.Count); + foreach (var elem in source) + tmp235.Add((elem != null) ? elem.DeepCopy() : null); + return tmp235; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp236 = new List(source.Count); + foreach (var elem in source) + tmp236.Add(elem); + return tmp236; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp237 = new List(source.Count); + foreach (var elem in source) + tmp237.Add((elem != null) ? elem.DeepCopy() : null); + return tmp237; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp238 = new List(source.Count); + foreach (var elem in source) + tmp238.Add((elem != null) ? elem.DeepCopy() : null); + return tmp238; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp239 = new List(source.Count); + foreach (var elem in source) + tmp239.Add(elem); + return tmp239; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp240 = new List(source.Count); + foreach (var elem in source) + tmp240.Add((elem != null) ? elem : null); + return tmp240; + } + + + } +} diff --git a/Tests/RPC/Client/Model/gRPCModel.proto b/Tests/RPC/Client/Model/gRPCModel.proto new file mode 100644 index 0000000..99a3708 --- /dev/null +++ b/Tests/RPC/Client/Model/gRPCModel.proto @@ -0,0 +1,244 @@ +syntax = "proto3"; + +package gpmodel; + +option csharp_namespace = "Echo.Model.Grpc"; + +// ========================= Enums ========================= + +enum Currency { + CURRENCY_IQD = 0; + CURRENCY_CNH = 1; + CURRENCY_USD = 2; + CURRENCY_EUR = 3; + CURRENCY_JPY = 4; + CURRENCY_GBP = 5; +} + +enum DocType { + DOC_TYPE_QUOTE = 0; + DOC_TYPE_ORDER = 1; + DOC_TYPE_INVOICE = 2; + DOC_TYPE_CREDIT_NOTE = 3; +} + +enum PaymentMethod { + PAYMENT_METHOD_CASH = 0; + PAYMENT_METHOD_CARD = 1; + PAYMENT_METHOD_WIRE = 2; + PAYMENT_METHOD_CRYPTO = 3; + PAYMENT_METHOD_OTHER = 4; +} + +enum LineType { + LINE_TYPE_PRODUCT = 0; + LINE_TYPE_SERVICE = 1; + LINE_TYPE_DISCOUNT = 2; + LINE_TYPE_SHIPPING = 3; +} + +// Variant.Kind +enum Kind { + KIND_NULL = 0; + KIND_BOOL = 1; + KIND_INT64 = 2; + KIND_UINT64 = 3; + KIND_DOUBLE = 4; + KIND_DECIMAL = 5; + KIND_STRING = 6; + KIND_BYTES = 7; + KIND_DATETIME = 8; + KIND_GUID = 9; +} + +// ========================= Variant ========================= +// +// C# Variant: +// Tag: Kind +// Bool: bool? +// I64: long? +// U64: ulong? +// F64: double? +// Str: string? +// Bytes: byte[]? +// Dt: DateTime? -> int64 (ticks or epoch millis) +// Guid: byte[]? + +message Variant { + Kind tag = 1; + bool bool_val = 2; // optional in C# + int64 i64_val = 3; // optional in C# + uint64 u64_val = 4; // optional in C# + double f64_val = 5; // optional in C# + string str_val = 6; // optional in C# + bytes bytes_val = 7; // optional in C# + int64 dt_val = 8; // optional in C# (DateTime) + bytes guid_val = 9; // optional in C# (Guid as 16-byte array) +} + +// Optional helpers mirroring MetaEntry / ExtEntry (not required for RPC) +message MetaEntry { + string key = 1; + Variant value = 2; +} + +message ExtEntry { + string key = 1; + Variant value = 2; +} + +// ========================= Address & Party ========================= + +message Address { + string line1 = 1; + optional string line2 = 2; // optional in C# + string city = 3; + string region = 4; + string country = 5; + optional string postal_code = 6; // optional in C# +} + +message Party { + uint64 id = 1; + string name = 2; + string tax_id = 3; // optional in C# + string email = 4; // optional in C# + string phone = 5; // optional in C# + Address address = 6; // optional in C# + string preferred_language = 7; // optional in C# +} + +// ========================= DocumentHeader ========================= +// +// DateTime/DateTime? -> int64 (ticks or epoch millis, your choice) + +message DocumentHeader { + bytes doc_id = 1; + DocType type = 2; + int32 version = 3; + int64 created_at = 4; // DateTime + optional int64 updated_at = 5; // optional in C# + Currency currency = 6; + string notes = 7; // optional in C# + map meta = 8; +} + +// ========================= LineItem, Payment, Attachment ========================= + +message LineItem { + int32 line_no = 1; + LineType type = 2; + string sku = 3; + string description = 4; + double qty = 5; + string qty_unit = 6; + double unit_price = 7; + optional double vat_rate = 8; // optional in C# + optional double discount = 9; // optional in C# + map ext = 10; +} + +message Payment { + PaymentMethod method = 1; + double amount = 2; + string reference = 3; // optional in C# + int64 timestamp = 4; // DateTime + double fee = 5; // optional in C# + Currency currency = 6; +} + +message Attachment { + string name = 1; + string mime_type = 2; + bytes data = 3; +} + +// ========================= Top-level BusinessDocument ========================= + +message BusinessDocument { + DocumentHeader header = 1; + Party seller = 2; + Party buyer = 3; + repeated LineItem items = 4; + repeated Payment payments = 5; + repeated Attachment attachments = 6; + repeated int32 risk_scores = 7; +} + +// ========================= Echo Service Messages ========================= +// +// C# signatures: +// +// byte[] EchoBytes(byte[]) +// BusinessDocument[] EchoDocuments(BusinessDocument[] docs) +// int[] EchoIntArray(int[] array) +// string[] EchoStringArray(string[] array) +// Map EchoMap(Map map) +// DocType EchoEnumArray(DocType[] docTypes); + +// --- Bytes --- +message BytesRequest { + bytes data = 1; +} + +// --- Bytes --- +message BytesResponse { + bytes data = 1; +} + + +// --- Documents --- +message DocumentsRequest { + repeated BusinessDocument docs = 1; +} + +message DocumentsResponse { + repeated BusinessDocument docs = 1; +} + +// --- Int array --- +message IntArrayRequest { + repeated int32 array = 1; +} + +message IntArrayResponse { + repeated int32 array = 1; +} + +// --- String array --- +message StringArrayRequest { + repeated string array = 1; +} + +message StringArrayResponse { + repeated string array = 1; +} + +// --- Map --- +message DocMapRequest { + map map = 1; +} + +message DocMapResponse { + map map = 1; +} + +// --- Enum array (returns a single DocType, e.g. last element) --- +message EnumArrayRequest { + repeated DocType doc_types = 1; +} + +message EnumResponse { + repeated DocType doc_types = 1; +} + +// ========================= Echo Service ========================= + +service EchoService { + rpc EchoBytes (BytesRequest) returns (BytesResponse); + rpc EchoDocuments (DocumentsRequest) returns (DocumentsResponse); + rpc EchoIntArray (IntArrayRequest) returns (IntArrayResponse); + rpc EchoStringArray (StringArrayRequest) returns (StringArrayResponse); + rpc EchoMap (DocMapRequest) returns (DocMapResponse); + rpc EchoEnumArray (EnumArrayRequest) returns (EnumResponse); +} diff --git a/Tests/RPC/Client/Program.cs b/Tests/RPC/Client/Program.cs new file mode 100644 index 0000000..de3ffb0 --- /dev/null +++ b/Tests/RPC/Client/Program.cs @@ -0,0 +1,128 @@ +using MQTTnet; +using RPC.Client.Tests; +using RPC.Client.Tests.Docs; +using RPC.Client.Tests.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static RPC.Client.Tests.Events.Websockets; + + +var results = new Dictionary>(); + +results.Add("esiur", new List()); +results.Add("grpc", new List()); +results.Add("thrift", new List()); +results.Add("json", new List()); +results.Add("signalr", new List()); + +for (var i = 0; i < 10; i++) +{ + var seed = 1000 + (i * 1000); + + var docsWorkloads = new Dictionary();// RPC.Client.Tests.DocGenerator.BuildWorkloads(seed); + var dataWorkLoads = Shared.BuildBytesWorkLoads(seed); + var intWorkloads = Shared.BuildIntWorkloads(seed); + + results["esiur"].Add( + await EsiurTest.DoTest("iip://localhost:5005/sys/service", docsWorkloads, dataWorkLoads, intWorkloads) + ); + + results["thrift"].Add( + await ThriftTest.DoTest("127.0.0.1", 5400, + docsWorkloads.ToDictionary(x => x.Key, v => v.Value.Select(x => x.ToThrift()).ToArray()), + dataWorkLoads, + intWorkloads + ) + ); + + results["signalr"].Add(await SignalRTest.DoTest("http://127.0.0.1:5200/hub/echo", + docsWorkloads.ToDictionary(x => x.Key, v => v.Value.Select(x => x.ToShared()).ToArray()), + dataWorkLoads, + intWorkloads + )); + + results["json"].Add( await JsonTest.DoTest("http://127.0.0.1:5100", + docsWorkloads, + dataWorkLoads, + intWorkloads + ) ); + + results["grpc"].Add(await GrpcTest.DoTest("http://127.0.0.1:5300", + docsWorkloads.ToDictionary(x => x.Key, v => v.Value.Select(x => x.ToGrpc()).ToArray()), + dataWorkLoads, + intWorkloads + )); +} + +// Compute statistics: average, min, max, median for tx/rx per transport and workload +static (double avg, long min, long max, double median) StatsLongs(List xs) +{ + if (xs == null || xs.Count == 0) return (double.NaN, 0, 0, double.NaN); + xs.Sort(); + double avg = xs.Average(x => (double)x); + long min = xs.First(); + long max = xs.Last(); + double median = xs.Count % 2 == 1 ? xs[xs.Count / 2] : 0.5 * (xs[xs.Count / 2 - 1] + xs[xs.Count / 2]); + return (avg, min, max, median); +} + +foreach (var transport in results.Keys) +{ + Console.WriteLine($"\n== Stats for {transport} =="); + + var rounds = results[transport]; + if (rounds.Count == 0) + { + Console.WriteLine("No results."); + continue; + } + + // categories: Docs, Bytes, Ints + var categories = new Dictionary>>() + { + { "Docs", tr => tr.Docs }, + { "Bytes", tr => tr.Bytes }, + { "Ints", tr => tr.Ints } + }; + + foreach (var cat in categories) + { + Console.WriteLine($"-- {cat.Key} --"); + + // collect all workload keys seen in any round + var allKeys = new HashSet(); + foreach (var r in rounds) + { + foreach (var k in cat.Value(r).Keys) allKeys.Add(k); + } + + foreach (var key in allKeys.OrderBy(k => k)) + { + var txList = new List(); + var rxList = new List(); + foreach (var r in rounds) + { + if (cat.Value(r).TryGetValue(key, out var tup)) + { + txList.Add(tup.Item1); + rxList.Add(tup.Item2); + } + } + + if (txList.Count == 0) + { + Console.WriteLine($"{key}: no samples"); + continue; + } + + var sTx = StatsLongs(txList); + var sRx = StatsLongs(rxList); + + Console.WriteLine($"{key}: TX avg={sTx.avg:0.##}, min={sTx.min}, max={sTx.max}, med={sTx.median:0.##} | RX avg={sRx.avg:0.##}, min={sRx.min}, max={sRx.max}, med={sRx.median:0.##}"); + } + } +} + diff --git a/Tests/RPC/Client/Protocol/echo.thrift b/Tests/RPC/Client/Protocol/echo.thrift new file mode 100644 index 0000000..9cd211c --- /dev/null +++ b/Tests/RPC/Client/Protocol/echo.thrift @@ -0,0 +1,179 @@ +namespace netstd Echo.ThriftModel + +// ====================== Enums ====================== + +enum Currency { + IQD = 0, + CNH = 1, + USD = 2, + EUR = 3, + JPY = 4, + GBP = 5 +} + +enum DocType { + Quote = 0, + Order = 1, + Invoice = 2, + CreditNote = 3 +} + +enum PaymentMethod { + Cash = 0, + Card = 1, + Wire = 2, + Crypto = 3, + Other = 4 +} + +enum LineType { + Product = 0, + Service = 1, + Discount = 2, + Shipping = 3 +} + +// Variant.Kind +enum Kind { + Null = 0, + Bool = 1, + Int64 = 2, + UInt64 = 3, + Double = 4, + Decimal = 5, + String = 6, + Bytes = 7, + DateTime = 8, + Guid = 9 +} + +// ====================== Core Value Types ====================== + +// C# Variant: +// Tag: Kind +// Bool: bool? -> optional bool +// I64: long? -> optional i64 +// U64: ulong? -> optional i64 (store unsigned in signed range or with convention) +// F64: double? -> optional double +// Str: string? -> optional string +// Bytes: byte[]? -> optional binary +// Dt: DateTime? -> optional i64 (e.g., Unix epoch millis or ticks) +// Guid: byte[]? -> optional binary +struct Variant { + 1: Kind tag, + 2: optional bool boolVal, + 3: optional i64 i64Val, + 4: optional i64 u64Val, + 5: optional double f64Val, + 6: optional string strVal, + 7: optional binary bytesVal, + 8: optional i64 dtVal, + 9: optional binary guidVal +} + +// Optional helper view of a meta/ext entry (not strictly required, +// since we use map below, but kept to mirror the graph). +struct MetaEntry { + 1: string key, + 2: Variant value +} + +struct ExtEntry { + 1: string key, + 2: Variant value +} + +// ====================== Party & Address ====================== + +struct Address { + 1: string line1, + 2: optional string line2, + 3: string city, + 4: string region, + 5: string country, + 6: optional string postalCode +} + +struct Party { + // C# ulong -> i64 (assumes IDs fit in signed 64-bit) + 1: i64 id, + 2: string name, + 3: optional string taxId, + 4: optional string email, + 5: optional string phone, + 6: optional Address address, + 7: optional string preferredLanguage +} + +// ====================== Document Header ====================== + +// DocId: byte[] +// Type: DocType +// Version: int +// CreatedAt: DateTime -> i64 (e.g. Unix ms) +// UpdatedAt: DateTime? -> optional i64 +// Currency: Currency +// Notes: string? +// Meta: Dictionary -> map +struct DocumentHeader { + 1: binary docId, + 2: DocType type, + 3: i32 version, + 4: i64 createdAt, + 5: optional i64 updatedAt, + 6: Currency currency, + 7: optional string notes, + 8: map meta +} + +// ====================== Line Items, Payments, Attachments ====================== + +struct LineItem { + 1: i32 lineNo, + 2: LineType type, + 3: string sku, + 4: string description, + 5: double qty, + 6: string qtyUnit, + 7: double unitPrice, + 8: optional double vatRate, + 9: optional double discount, + 10: map ext +} + +struct Payment { + 1: PaymentMethod method, + 2: double amount, + 3: optional string reference, + // DateTime -> i64 (e.g. Unix epoch millis or ticks) + 4: i64 timestamp, + 5: optional double fee, + 6: Currency currency +} + +struct Attachment { + 1: string name, + 2: string mimeType, + 3: binary data +} + +// ====================== Top-Level Document ====================== + +struct BusinessDocument { + 1: DocumentHeader header, + 2: Party seller, + 3: Party buyer, + 4: list items, + 5: list payments, + 6: list attachments, + 7: list riskScores +} + +service EchoService { + binary EchoBytes(1: binary data), + list EchoDocuments(1: list docs), + list EchoIntArray(1: list array), + list EchoStringArray(1: list array), + map EchoMap(1: map map), + list EchoEnumArray(1: list docTypes) +} diff --git a/Tests/RPC/Client/Tests/DocGenerator.cs b/Tests/RPC/Client/Tests/DocGenerator.cs new file mode 100644 index 0000000..baa517b --- /dev/null +++ b/Tests/RPC/Client/Tests/DocGenerator.cs @@ -0,0 +1,433 @@ +using Esiur.Data; +using RPC.EsiurTest; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + + +#nullable enable +namespace RPC.Client.Tests; + +public static class DocGenerator +{ + public sealed class GenOptions + { + public int Lines { get; init; } = 20; // items count + public int Attachments { get; init; } = 0; // 0..N + public int AttachmentBytes { get; init; } = 0;// per attachment + public int Payments { get; init; } = 1; // 0..N + public bool IncludeV2Fields { get; init; } = false; + public bool IncludeUnicode { get; init; } = true; // Arabic/emoji sprinkled in + public int VariantPerLine { get; init; } = 1; // ad-hoc KV per line + public Currency Currency { get; init; } = Currency.USD; + + public int RiskScores { get; set; } = 20; + public int Seed { get; init; } = 12345; + } + + public static BusinessDocument MakeBusinessDocument(GenOptions? options = null) + { + var opt = options ?? new GenOptions(); + var rng = new Random(opt.Seed); + + var seller = MakeParty(rng, opt.IncludeV2Fields, isSeller: true, opt.IncludeUnicode); + var buyer = MakeParty(rng, opt.IncludeV2Fields, isSeller: false, opt.IncludeUnicode); + + var createdAt = DateTime.UtcNow.AddMinutes(-rng.Next(0, 60 * 24)); + var doc = new BusinessDocument + { + Header = new DocumentHeader + { + DocId = Guid.NewGuid().ToByteArray(), + Type = (DocType)rng.Next(0, 4), + Version = 1, + CreatedAt = createdAt, + UpdatedAt = null, + Currency = opt.Currency, + Notes = opt.IncludeUnicode ? SampleNoteUnicode(rng) : SampleNoteAscii(rng), + Meta = new Map + { + ["source"] = VStr("benchmark"), + ["region"] = VStr("ME"), + ["channel"] = VStr(rng.Next(0, 2) == 0 ? "online" : "pos"), + } + }, + Seller = seller, + Buyer = buyer, + Items = new LineItem[opt.Lines], + Payments = opt.Payments > 0 ? new Payment[opt.Payments] : null, + Attachments = opt.Attachments > 0 ? new Attachment[opt.Attachments] : null, + + RiskScores = RandomRiskScores(rng, opt.RiskScores), + //RelatedDocs_v2 = opt.IncludeV2Fields ? new List { Guid.NewGuid(), Guid.NewGuid() } : null + }; + + + // Items + for (int i = 0; i < opt.Lines; i++) + doc.Items[i] = MakeLineItem(rng, i + 1, opt.IncludeV2Fields, opt.VariantPerLine, opt.IncludeUnicode); + + // Payments + if (doc.Payments != null) + { + var grand = doc.Items.Sum(L => L.UnitPrice * L.Qty * (double)(1.0 - (L.Discount ?? 0.0) / 100.0)); + var remain = grand; + for (int i = 0; i < opt.Payments; i++) + { + var last = (i == opt.Payments - 1); + var amt = last ? remain : RoundMoney((double)rng.NextDouble() * remain * 0.7 + 1.0); + remain = Math.Max(0.0, remain - amt); + doc.Payments[i] = MakePayment(rng, amt, opt.IncludeV2Fields); + } + } + + // Attachments + if (doc.Attachments != null) + { + for (int i = 0; i < opt.Attachments; i++) + doc.Attachments[i] = MakeAttachment(rng, i, opt.AttachmentBytes); + } + + return doc; + } + + /// + /// Create a slightly modified copy of an existing document to test delta/partial updates. + /// Changes: tweak 5–10% of line items (qty/price), add or edit a payment, and bump UpdatedAt. + /// + public static BusinessDocument MakeDelta(BusinessDocument v1, int seed, double changeRatio = 0.07) + { + var rng = new Random(seed); + var v2 = DeepClone(v1); + + v2.Header.UpdatedAt = DateTime.UtcNow; + var toChange = Math.Max(1, (int)Math.Round(v2.Items.Length * changeRatio)); + + // change random lines + for (int i = 0; i < toChange; i++) + { + var idx = rng.Next(0, v2.Items.Length); + var li = v2.Items[idx]; + li.Qty = RoundQty(li.Qty + (double)(rng.NextDouble() * 2.0 - 1.0)); // ±1 + li.UnitPrice = RoundMoney(li.UnitPrice * (double)(0.95 + rng.NextDouble() * 0.1)); // ±5% + if (li.Ext == null) li.Ext = new Map(); + li.Ext["lastEdit"] = VDate(DateTime.UtcNow); + } + + + if (v2.Payments == null || rng.Next(0, 3) == 0) + { + if (v2.Payments == null) + { + if (v2.Payments == null) v2.Payments = new Payment[1]; + v2.Payments[0] = (MakePayment(rng, RoundMoney((double)rng.NextDouble() * 50.0 + 10.0), includeV2: true)); + + } + else + { + v2.Payments = v2.Payments.Append((MakePayment(rng, RoundMoney((double)rng.NextDouble() * 50.0 + 10.0), includeV2: true))).ToArray(); + } + } + else + { + var p = v2.Payments[rng.Next(0, v2.Payments.Length)]; + p.Fee = (p.Fee ?? 0.0) + 0.25; + p.Reference = "ADJ-" + rng.Next(10000, 99999).ToString(CultureInfo.InvariantCulture); + } + + return v2; + } + + // -------------------------- Builders -------------------------- + + private static int[] RandomRiskScores(Random rng, int count) + { + + var rt = new int[count];// rng.Next(100, 1000)]; + for (var i = 0; i < rt.Length; i++) + rt[i] = (int)rng.Next(); + return rt; + } + + private static Party MakeParty(Random rng, bool includeV2, bool isSeller, bool unicode) + { + return new Party + { + Id = (ulong)rng.NextInt64(), //Guid.NewGuid().ToByteArray(), + Name = unicode ? (isSeller ? "Delta Systems — دلتا" : "Client التجربة ✅") : (isSeller ? "Delta Systems" : "Client Demo"), + TaxId = isSeller ? $"TX-{rng.Next(100000, 999999)}" : null, + Email = (isSeller ? "sales" : "contact") + "@example.com", + Phone = "+964-7" + rng.Next(100000000, 999999999).ToString(CultureInfo.InvariantCulture), + Address = new Address + { + Line1 = rng.Next(0, 2) == 0 ? "Street 14" : "Tech Park", + City = "Baghdad", + Region = "BG", + Country = "IQ", + PostalCode = rng.Next(0, 2) == 0 ? "10001" : null + }, + PreferredLanguage = includeV2 ? (rng.Next(0, 2) == 0 ? "ar-IQ" : "en-US") : null + }; + } + + private static LineItem MakeLineItem(Random rng, int lineNo, bool includeV2, int variantKvp, bool unicode) + { + var isProduct = rng.Next(0, 100) < 80; + var desc = unicode + ? (isProduct ? $"وحدة قياس — Item {lineNo} 🔧" : $"خدمة دعم — Service {lineNo} ✨") + : (isProduct ? $"Item {lineNo}" : $"Service {lineNo}"); + + var li = new LineItem + { + LineNo = lineNo, + Type = isProduct ? LineType.Product : LineType.Service, + SKU = isProduct ? ("SKU-" + rng.Next(1000, 9999)) : "", + Description = desc, + Qty = RoundQty((double)(rng.NextDouble() * 9.0 + 1.0)), // 1..10 + QtyUnit = isProduct ? "pcs" : "h", + UnitPrice = RoundMoney((double)(rng.NextDouble() * 90.0 + 10.0)), + VatRate = rng.Next(0, 100) < 80 ? 5.0 : (double?)null, + Ext = variantKvp > 0 ? new Map() : null, + Discount = includeV2 && rng.Next(0, 3) == 0 ? Math.Round(rng.NextDouble() * 10.0, 2) : (double?)null + }; + + + for (int i = 0; i < variantKvp; i++) + { + var key = i switch { 0 => "color", 1 => "size", 2 => "batch", _ => "attr" + i }; + li.Ext!.Add(key, i switch + { + 0 => VStr(rng.Next(0, 3) switch { 0 => "red", 1 => "blue", _ => "green" }), + 1 => VStr(rng.Next(0, 3) switch { 0 => "S", 1 => "M", _ => "L" }), + 2 => VGuid(Guid.NewGuid()), + _ => VInt(rng.Next(0, 1000)) + }); + } + + return li; + } + + private static Payment MakePayment(Random rng, double amount, bool includeV2) + { + var p = new Payment + { + Method = (PaymentMethod)rng.Next(0, 5), + Amount = RoundMoney(amount), + Reference = "REF-" + rng.Next(100_000, 999_999), + Timestamp = DateTime.UtcNow.AddMinutes(-rng.Next(0, 60 * 24)), + Fee = includeV2 && rng.Next(0, 2) == 0 ? RoundMoney((double)rng.NextDouble() * 2.0) : null, + //CurrencyOverride = includeV2 && rng.Next(0, 2) == 0 ? Currency.IQD : Currency.USD + }; + + + return p; + } + + private static Attachment MakeAttachment(Random rng, int index, int bytes) + { + var arr = bytes > 0 ? new byte[bytes] : Array.Empty(); + if (arr.Length > 0) rng.NextBytes(arr); + return new Attachment + { + Name = $"att-{index + 1}.bin", + MimeType = "application/octet-stream", + Data = arr + }; + } + + private static string SampleNoteUnicode(Random rng) + => rng.Next(0, 2) == 0 + ? "ملاحظة: تم إنشاء هذا المستند لأغراض الاختبار 📦" + : "Note: synthetic benchmark document 🧪"; + + private static string SampleNoteAscii(Random rng) + => rng.Next(0, 2) == 0 ? "Note: synthetic benchmark document" : "Internal use only"; + + // -------------------------- Variant helpers -------------------------- + private static Variant VStr(string s) => new() { Tag = Kind.String, Str = s }; + private static Variant VInt(int v) => new() { Tag = Kind.Int64, I64 = v }; + private static Variant VGuid(Guid g) => new() { Tag = Kind.Guid, Guid = g.ToByteArray() }; + private static Variant VDate(DateTime d) => new() { Tag = Kind.DateTime, Dt = d }; + + // -------------------------- Utils -------------------------- + private static double RoundMoney(double v) => Math.Round(v, 2, MidpointRounding.AwayFromZero); + private static double RoundQty(double v) => Math.Round(v, 3, MidpointRounding.AwayFromZero); + + /// + /// Simple deep clone via manual copy to stay serializer-agnostic. + /// (Good enough for benchmarks; switch to a fast serializer if you like.) + /// + private static BusinessDocument DeepClone(BusinessDocument s) + { + var d = new BusinessDocument + { + Header = new DocumentHeader + { + DocId = s.Header.DocId, + Type = s.Header.Type, + Version = s.Header.Version, + CreatedAt = s.Header.CreatedAt, + UpdatedAt = s.Header.UpdatedAt, + //CreatedAtAsLong = s.Header.CreatedAtAsLong, + //UpdatedAtAsLong = s.Header.UpdatedAtAsLong, + Currency = s.Header.Currency, + Notes = s.Header.Notes, + Meta = s.Header.Meta, + }, + Seller = CloneParty(s.Seller), + Buyer = CloneParty(s.Buyer), + Items = s.Items.Select(CloneLine).ToArray(), + Payments = s.Payments?.Select(ClonePayment).ToArray(), + Attachments = s.Attachments?.Select(CloneAttachment).ToArray(), + RiskScores = s.RiskScores, + //RelatedDocs_v2 = s.RelatedDocs_v2?.ToList() + }; + + + return d; + } + + private static Party CloneParty(Party p) => new() + { + Id = p.Id, + Name = p.Name, + TaxId = p.TaxId, + Email = p.Email, + Phone = p.Phone, + Address = p.Address is null ? null : new Address + { + Line1 = p.Address.Line1, + Line2 = p.Address.Line2, + City = p.Address.City, + Region = p.Address.Region, + Country = p.Address.Country, + PostalCode = p.Address.PostalCode + }, + PreferredLanguage = p.PreferredLanguage + }; + + private static LineItem CloneLine(LineItem s) => new() + { + LineNo = s.LineNo, + Type = s.Type, + SKU = s.SKU, + Description = s.Description, + Qty = s.Qty, + QtyUnit = s.QtyUnit, + UnitPrice = s.UnitPrice, + VatRate = s.VatRate, + Ext = s.Ext, + Discount = s.Discount, + }; + + private static Payment ClonePayment(Payment s) => new() + { + Method = s.Method, + Amount = s.Amount, + Reference = s.Reference, + Timestamp = s.Timestamp, + Fee = s.Fee, + }; + + private static Attachment CloneAttachment(Attachment s) => new() + { + Name = s.Name, + MimeType = s.MimeType, + Data = s.Data.ToArray() + }; + + private static Variant CloneVariant(Variant v) => new() + { + Tag = v.Tag, + Bool = v.Bool, + I64 = v.I64, + U64 = v.U64, + F64 = v.F64, + //Dec = v.Dec, + Str = v.Str, + Bytes = v.Bytes?.ToArray(), + Dt = v.Dt, + Guid = v.Guid + }; + + + + public static Dictionary BuildWorkloads(int seed = 1000) + { + var result = new Dictionary(); + + // Small + { + var items = new List(); + for (int i = 0; i < 16; i++) + { + var doc = DocGenerator.MakeBusinessDocument(new DocGenerator.GenOptions + { + Lines = 5, + Payments = 3, + Attachments = 0, + IncludeV2Fields = (i % 2 == 0), + IncludeUnicode = true, + RiskScores = 100, + Seed = 1000 + i + }); + + items.Add(doc); + } + + result.Add("Small", items.ToArray()); + } + + // Medium + { + var items = new List(); + for (int i = 0; i < 16; i++) + { + var doc = DocGenerator.MakeBusinessDocument(new DocGenerator.GenOptions + { + Lines = 20, + Payments = 5, + Attachments = 1, + AttachmentBytes = 8 * 1024, + IncludeV2Fields = (i % 3 == 0), + IncludeUnicode = true, + RiskScores = 1000, + Seed = 2000 + i + }); + + items.Add(doc); + } + + result.Add("Medium", items.ToArray()); + } + + // Large + { + var items = new List(); + + for (int i = 0; i < 12; i++) + { + var doc = DocGenerator.MakeBusinessDocument(new DocGenerator.GenOptions + { + Lines = 100, + Payments = 20, + Attachments = 3, + AttachmentBytes = 64 * 1024, + IncludeV2Fields = (i % 2 == 1), + IncludeUnicode = true, + RiskScores = 3000, + Seed = 3000 + i + }); + + items.Add(doc); + } + result.Add("Large", items.ToArray()); + } + + return result; + } + + +} diff --git a/Tests/RPC/Client/Tests/Docs/EsiurTest.cs b/Tests/RPC/Client/Tests/Docs/EsiurTest.cs new file mode 100644 index 0000000..ac74dfd --- /dev/null +++ b/Tests/RPC/Client/Tests/Docs/EsiurTest.cs @@ -0,0 +1,139 @@ +using Esiur.Net.Sockets; +using Esiur.Resource; +using RPC.EsiurTest; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Esiur.Misc; +using Esiur.Data; + +namespace RPC.Client.Tests.Docs +{ + public static class EsiurTest + { + public static async Task DoTest(string address, + Dictionary docsWorkloads, + Dictionary dataWorkloads, + Dictionary intWorkloads ) + { + + var rt = new TestResults(); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + Console.WriteLine($"\n== Esiur @ {address} =="); + + var service = await Warehouse.Default.Get(address); + + var sock = service.ResourceConnection.Socket as TcpSocket; + + + Thread.Sleep(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + await Task.Delay(2000); + + foreach (var w in docsWorkloads) + { + Console.Write("Workload: " + w.Key); + var docs = await service.EchoDocuments(w.Value); + + + for (var i = 0; i < docs.Length; i++) + if (!docs[i].Equals(w.Value[i])) + throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Docs.Add(w.Key, (ctx, crx)); + } + + + + foreach (var w in dataWorkloads) + { + Console.Write("Bytes Workload: " + w.Key); + var res = await service.EchoBytes(w.Value); + + + if (!w.Value.SequenceEqual(res)) + throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Bytes.Add(w.Key, (ctx, crx)); + + } + + + foreach (var w in intWorkloads) + { + Console.Write("Ints Workload: " + w.Key); + var res = await service.EchoIntArray(w.Value); + + + if (!w.Value.SequenceEqual(res)) + throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + + rt.Ints.Add(w.Key, (ctx, crx)); + + } + + await Task.Delay(3000); + + (tx, rx) = mon.GetTotals(); + Console.WriteLine($"Transfer {tx}/{rx}"); + Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + mon.Stop(); + + return rt; + } + + //public static async Task Do(string address) + //{ + // Console.WriteLine($"\n== Esiur @ {address} =="); + + // var service = await Warehouse.Default.Get(address); + + // var workloads = DocGenerator.BuildWorkloads(); + + // foreach (var w in workloads) + // { + // Console.WriteLine("Workload: " + w.Item1); + // var rx = await service.EchoDocuments(w.Item2); + + // for (var i = 0; i < rx.Length; i++) + // if (!rx[i].Equals(w.Item2[i])) + // throw new Exception("No match"); + // } + //} + + + } +} diff --git a/Tests/RPC/Client/Tests/Docs/GrpcTest.cs b/Tests/RPC/Client/Tests/Docs/GrpcTest.cs new file mode 100644 index 0000000..b05fa1a --- /dev/null +++ b/Tests/RPC/Client/Tests/Docs/GrpcTest.cs @@ -0,0 +1,118 @@ +using Echo.Model.Grpc; +using Esiur.Net.Sockets; +using Esiur.Resource; +using Google.Protobuf; +using Grpc.Net.Client; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace RPC.Client.Tests.Docs; + +public class GrpcTest +{ + + public static async Task DoTest(string address, + Dictionary docsWorkloads, + Dictionary dataWorkloads, + Dictionary intWorkloads) + { + var rt = new TestResults(); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + Console.WriteLine($"\n== Grpc @ {address} =="); + + using var channel = GrpcChannel.ForAddress(address); + var service = new Echo.Model.Grpc.EchoService.EchoServiceClient(channel); + + + Thread.Sleep(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + await Task.Delay(2000); + + foreach (var w in docsWorkloads) + { + Console.Write("Workload: " + w.Key); + var rd = new DocumentsRequest(); + rd.Docs.AddRange(w.Value); + var docs = await service.EchoDocumentsAsync(rd); + + + //for (var i = 0; i < docs.Length; i++) + // if (!docs[i].Equals(w.Value[i])) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + + rt.Docs.Add(w.Key, (ctx, crx)); + + } + + + + foreach (var w in dataWorkloads) + { + Console.Write("Bytes Workload: " + w.Key); + + var br = new BytesRequest() { Data = ByteString.CopyFrom(w.Value) }; + var res = await service.EchoBytesAsync(br); + + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Bytes.Add(w.Key, (ctx, crx)); + + } + + + foreach (var w in intWorkloads) + { + Console.Write("Ints Workload: " + w.Key); + + var ir = new IntArrayRequest(); + ir.Array.AddRange(w.Value); + + var res = await service.EchoIntArrayAsync(ir); + + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Ints.Add(w.Key, (ctx, crx)); + + } + + await Task.Delay(3000); + + (tx, rx) = mon.GetTotals(); + Console.WriteLine($"Transfer {tx}/{rx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + mon.Stop(); + + return rt; + } +} \ No newline at end of file diff --git a/Tests/RPC/Client/Tests/Docs/JsonTest.cs b/Tests/RPC/Client/Tests/Docs/JsonTest.cs new file mode 100644 index 0000000..c7a403d --- /dev/null +++ b/Tests/RPC/Client/Tests/Docs/JsonTest.cs @@ -0,0 +1,128 @@ +using RPC.EsiurTest; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace RPC.Client.Tests.Docs; + + +public class JsonTest +{ + + public static async Task DoTest(string address, + Dictionary docsWorkloads, + Dictionary dataWorkloads, + Dictionary intWorkloads) + { + var rt = new TestResults(); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + Console.WriteLine($"\n== JSON @ {address} =="); + + + using var http = new HttpClient { BaseAddress = new Uri(address) }; + + + Thread.Sleep(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + await Task.Delay(2000); + + foreach (var w in docsWorkloads) + { + Console.Write("Workload: " + w.Key); + var docs = await JsonRpcCallAsync(http, "EchoDocuments", w.Value); + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + + rt.Docs.Add(w.Key, (ctx, crx)); + + } + + + + foreach (var w in dataWorkloads) + { + Console.Write("Bytes Workload: " + w.Key); + + var res = await JsonRpcCallAsync(http, "EchoBytes", w.Value); + + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Bytes.Add(w.Key, (ctx, crx)); + + } + + + foreach (var w in intWorkloads) + { + Console.Write("Ints Workload: " + w.Key); + + var res = await JsonRpcCallAsync(http, "EchoIntArray", w.Value); + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Ints.Add(w.Key, (ctx, crx)); + + } + + await Task.Delay(3000); + + (tx, rx) = mon.GetTotals(); + Console.WriteLine($"Transfer {tx}/{rx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + mon.Stop(); + + return rt; + } + + + + // ===== JSON options ===== + static JsonSerializerOptions json = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + record JsonRpcReq(string Jsonrpc, string Method, object Params, string Id); + record JsonRpcRes { public string Jsonrpc { get; init; } = "2.0"; public string Id { get; init; } = "1"; public object? Result { get; init; } } + + public static async Task<(JsonElement root, string raw)> JsonRpcCallAsync(HttpClient http, string method, object param, bool noId = false) + { + var reqObj = new JsonRpcReq("2.0", method, param, "1"); + var jsonTxt = JsonSerializer.Serialize(reqObj, json); + var res = await http.PostAsync("/rpc", new StringContent(jsonTxt, Encoding.UTF8, "application/json")); + var raw = await res.Content.ReadAsStringAsync(); + res.EnsureSuccessStatusCode(); + if (noId) return (default, raw); + using var doc = JsonDocument.Parse(raw); + return (doc.RootElement.Clone(), raw); + } +} \ No newline at end of file diff --git a/Tests/RPC/Client/Tests/Docs/SignalRTest.cs b/Tests/RPC/Client/Tests/Docs/SignalRTest.cs new file mode 100644 index 0000000..0e0ce5c --- /dev/null +++ b/Tests/RPC/Client/Tests/Docs/SignalRTest.cs @@ -0,0 +1,143 @@ +using Esiur.Data; +using Esiur.Misc; +using Esiur.Net.Sockets; +using Esiur.Resource; +using Microsoft.AspNetCore.SignalR.Client; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace RPC.Client.Tests.Docs +{ + public static class SignalRTest + { + public static async Task DoTest(string address, + Dictionary docsWorkloads, + Dictionary dataWorkloads, + Dictionary intWorkloads) + { + + var rt = new TestResults(); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + Console.WriteLine($"\n== SignalR @ {address} =="); + + var service = new HubConnectionBuilder() + .WithUrl(address) + .WithAutomaticReconnect() + .Build(); + + + await service.StartAsync(); + + + Thread.Sleep(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + await Task.Delay(2000); + + foreach (var w in docsWorkloads) + { + Console.Write("Workload: " + w.Key); + await service.InvokeAsync("EchoDocuments", w.Value); + + + //for (var i = 0; i < docs.Length; i++) + // if (!docs[i].Equals(w.Value[i])) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Docs.Add(w.Key, (ctx, crx)); + + } + + + + foreach (var w in dataWorkloads) + { + Console.Write("Bytes Workload: " + w.Key); + await service.InvokeAsync("EchoBytes", w.Value); + + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Bytes.Add(w.Key, (ctx, crx)); + + } + + + foreach (var w in intWorkloads) + { + Console.Write("Ints Workload: " + w.Key); + await service.InvokeAsync("EchoIntArray", w.Value); + + + //if (!w.Value.SequenceEqual(rt)) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Ints.Add(w.Key, (ctx, crx)); + + } + + await Task.Delay(3000); + + (tx, rx) = mon.GetTotals(); + Console.WriteLine($"Transfer {tx}/{rx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + mon.Stop(); + + return rt; + } + + //public static async Task Do(string address) + //{ + // Console.WriteLine($"\n== Esiur @ {address} =="); + + // var service = await Warehouse.Default.Get(address); + + // var workloads = DocGenerator.BuildWorkloads(); + + // foreach (var w in workloads) + // { + // Console.WriteLine("Workload: " + w.Item1); + // var rx = await service.EchoDocuments(w.Item2); + + // for (var i = 0; i < rx.Length; i++) + // if (!rx[i].Equals(w.Item2[i])) + // throw new Exception("No match"); + // } + //} + + + } +} diff --git a/Tests/RPC/Client/Tests/Docs/ThriftTest.cs b/Tests/RPC/Client/Tests/Docs/ThriftTest.cs new file mode 100644 index 0000000..4f54fa1 --- /dev/null +++ b/Tests/RPC/Client/Tests/Docs/ThriftTest.cs @@ -0,0 +1,111 @@ +using Echo.ThriftModel; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace RPC.Client.Tests.Docs; + +public class ThriftTest +{ + + public static async Task DoTest(string host, int port, + Dictionary docsWorkloads, + Dictionary dataWorkloads, + Dictionary intWorkloads) + { + var rt = new TestResults(); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + Console.WriteLine($"\n== Thrift @ {host} =="); + + + using var socket = new Thrift.Transport.Client.TSocketTransport(host, port, new Thrift.TConfiguration()); + //await socket.OpenAsync(new CancellationToken()); + var proto = new Thrift.Protocol.TBinaryProtocol(socket); + var service = new Echo.ThriftModel.EchoService.Client(proto); + + + Thread.Sleep(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + + await Task.Delay(2000); + + foreach (var w in docsWorkloads) + { + Console.Write("Workload: " + w.Key); + var docs = await service.EchoDocuments(w.Value.ToList()); + + + //for (var i = 0; i < docs.Length; i++) + // if (!docs[i].Equals(w.Value[i])) + // throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + + rt.Docs.Add(w.Key, (ctx, crx)); + } + + + + foreach (var w in dataWorkloads) + { + Console.Write("Bytes Workload: " + w.Key); + + var res = await service.EchoBytes(w.Value); + + + if (!w.Value.SequenceEqual(res)) + throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Bytes.Add(w.Key, (ctx, crx)); + + } + + + foreach (var w in intWorkloads) + { + Console.Write("Ints Workload: " + w.Key); + + var res = await service.EchoIntArray(w.Value.ToList()); + + + if (!w.Value.SequenceEqual(res)) + throw new Exception("No match"); + + + await Task.Delay(3000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($", {tx}/{rx}, {ctx}/{crx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + rt.Ints.Add(w.Key, (ctx, crx)); + + } + + await Task.Delay(3000); + + (tx, rx) = mon.GetTotals(); + Console.WriteLine($"Transfer {tx}/{rx}"); + //Console.WriteLine($"Socket {sock.BytesSent}/{sock.BytesReceived}"); + + mon.Stop(); + + return rt; + } +} \ No newline at end of file diff --git a/Tests/RPC/Client/Tests/Events/EsiurEventsTest.cs b/Tests/RPC/Client/Tests/Events/EsiurEventsTest.cs new file mode 100644 index 0000000..2815c7c --- /dev/null +++ b/Tests/RPC/Client/Tests/Events/EsiurEventsTest.cs @@ -0,0 +1,114 @@ +using Esiur.Net.Sockets; +using Esiur.Resource; +using RPC.EsiurTest; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace RPC.Client.Tests.Events +{ + public class EsiurEventsTest + { + + public enum TestType + { + Chunk, + Event, + Property + } + + public static async Task DoTest(TestType type, string address, int count, int size, int delay) + { + var rt = new TestResults(); + //using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + //mon.Start(); + + + var service = await Warehouse.Default.Get(address); + var sock = service.ResourceConnection.Socket as TcpSocket; + + + //await Task.Delay(3000); + + //var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + if (type == TestType.Event) + service.EventTest(count, size, delay); + else if (type == TestType.Property) + service.PropertyChangeTest(count, size, delay); + else if (type == TestType.Chunk) + service.ChunkTest(count, size, delay); + + var crx = sock.BytesReceived; + var ctx = sock.BytesSent; + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + + await Task.Delay(7000 + (count * size)); + + crx = sock.BytesReceived - crx; + ctx = sock.BytesSent - ctx; + + //(tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + //Console.WriteLine($"Results {ctx}/{crx} Total: {tx}/{rx}"); + Console.WriteLine($"Results {ctx}/{crx}"); + + + } + + + public static async Task DoEventTest(string address, int count, int size, int delay) + { + var rt = new TestResults(); + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + + var service = await Warehouse.Default.Get(address); + + await service.EventTest(count, size, delay); + + await Task.Delay(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + + + await Task.Delay(7000 + (count * delay)); + + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($"Results {ctx}/{crx} Total: {tx}/{rx}"); + + } + + public static async Task DoPropertyTest(string address, int count, int size, int delay) + { + var rt = new TestResults(); + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + + var service = await Warehouse.Default.Get(address); + + await Task.Delay(3000); + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + await service.PropertyChangeTest(count, size, delay); + + + await Task.Delay(3000 + (size * delay)); + + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + Console.WriteLine($"Results {ctx}/{crx} Total: {tx}/{rx}"); + + } + + } +} diff --git a/Tests/RPC/Client/Tests/Events/MQTTClient.cs b/Tests/RPC/Client/Tests/Events/MQTTClient.cs new file mode 100644 index 0000000..505dfc7 --- /dev/null +++ b/Tests/RPC/Client/Tests/Events/MQTTClient.cs @@ -0,0 +1,128 @@ +// Benchmark MQTT client helper +// Usage: call BenchmarkClient.RunAsync("localhost", 1883, "welcome/topic/100/1024/0"); +// This class is not an executable by itself to avoid duplicate entry points in the project. + +using MQTTnet; +using MQTTnet.Protocol; +using RPC.Client.Tests; +using System; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +public static class MQTTTest +{ + public static async Task DoTest(string brokerHost = "localhost", int brokerPort = 1883, string topic = "test/topic/100/100/100", CancellationToken cancellationToken = default) + { + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + var factory = new MqttClientFactory(); + using var mqttClient = factory.CreateMqttClient(); + + var options = new MqttClientOptionsBuilder() + .WithTcpServer(brokerHost, brokerPort) + .WithCleanSession() + .Build(); + + long receivedMessages = 0; + long receivedBytes = 0; + DateTime? firstReceivedAt = null; + DateTime? lastReceivedAt = null; + + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + mqttClient.ApplicationMessageReceivedAsync += (e => + { + var now = DateTime.UtcNow; + + Interlocked.Increment(ref receivedMessages); + Interlocked.Add(ref receivedBytes, e.ApplicationMessage?.Payload.Length ?? 0); + + if (firstReceivedAt == null) + { + firstReceivedAt = now; + } + + lastReceivedAt = now; + + // If expected count encoded in topic, check completion + var segments = topic.Split('/', StringSplitOptions.RemoveEmptyEntries); + if (segments.Length >= 5 && int.TryParse(segments[2], out var expected) && expected > 0) + { + if (Interlocked.Read(ref receivedMessages) >= expected) + { + tcs.TrySetResult(true); + } + } + + return Task.CompletedTask; + }); + + mqttClient.ConnectedAsync += (async e => + { + Console.WriteLine($"Connected to {brokerHost}:{brokerPort}"); + await mqttClient.SubscribeAsync(new MqttClientSubscribeOptionsBuilder() + .WithTopicFilter(f => { f.WithTopic(topic).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce); }) + .Build()); + + Console.WriteLine($"Subscribed to topic '{topic}'"); + }); + + + + //mqttClient.DisconnectedAsync += (e => Console.WriteLine("Disconnected from broker")); + + await mqttClient.ConnectAsync(options, cancellationToken); + + await Task.Delay(1000); + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + Console.WriteLine($"Handshake {ctx}/{crx}"); + + // If no expected count, wait until cancelled + var segmentsCheck = topic.Split('/', StringSplitOptions.RemoveEmptyEntries); + Task waitTask; + if (segmentsCheck.Length >= 5 && int.TryParse(segmentsCheck[2], out var expectedCount) && expectedCount > 0) + { + // wait for expected messages or cancellation + waitTask = Task.WhenAny(tcs.Task, Task.Run(() => { var ct = new CancellationTokenSource(); cancellationToken.Register(ct.Cancel); return Task.Delay(Timeout.Infinite, ct.Token); })).Unwrap(); + await waitTask; + } + else + { + // wait until cancellation + try + { + await Task.Delay(Timeout.Infinite, cancellationToken); + } + catch (TaskCanceledException) { } + } + + // compute results + var totalMsgs = Interlocked.Read(ref receivedMessages); + var totalBytes = Interlocked.Read(ref receivedBytes); + var duration = (lastReceivedAt.HasValue && firstReceivedAt.HasValue) ? (lastReceivedAt.Value - firstReceivedAt.Value) : TimeSpan.Zero; + + Console.WriteLine("--- Benchmark results ---"); + Console.WriteLine($"Messages received: {totalMsgs}"); + Console.WriteLine($"Total bytes: {totalBytes}"); + Console.WriteLine($"Duration (first->last): {duration.TotalSeconds:F3} s"); + Console.WriteLine($"Messages/sec: {(duration.TotalSeconds > 0 ? (totalMsgs / duration.TotalSeconds) : 0):F3}"); + Console.WriteLine($"Bytes/sec: {(duration.TotalSeconds > 0 ? (totalBytes / duration.TotalSeconds) : 0):F3}"); + + + await Task.Delay(2000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + + Console.WriteLine($"Results {ctx}/{crx} Total: {tx}/{rx}"); + + try + { + await mqttClient.DisconnectAsync(); + } + catch { } + } + +} diff --git a/Tests/RPC/Client/Tests/Events/SSE.cs b/Tests/RPC/Client/Tests/Events/SSE.cs new file mode 100644 index 0000000..49bff4f --- /dev/null +++ b/Tests/RPC/Client/Tests/Events/SSE.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Diagnostics; + +namespace RPC.Client.Tests.Events; + + + +// Simple SSE client helper for benchmarking the /sse endpoint. +// Usage: +// var opts = new SseOptions { MessagesPerBurst = 10, MessageSize = 512, IntervalMs = 10, BurstIntervalMs = 1000 }; +// await SseClient.ConnectAsync("http://localhost:5000/sse", opts, CancellationToken.None, +// onMessage: data => Console.WriteLine("msg:" + data.Length), onOpen: () => Console.WriteLine("open"), onError: ex => Console.WriteLine(ex)); +public static class SseClient +{ + public static async Task DoTest(string baseUrl, SseOptions options, CancellationToken ct, + Action? onMessage = null, Action? onOpen = null, Action? onError = null) + { + + Console.WriteLine("Starting SSE client..." ); + + options ??= new SseOptions(); + + var url = BuildUrl(baseUrl, options); + + using var http = new HttpClient() { Timeout = Timeout.InfiniteTimeSpan }; + var req = new HttpRequestMessage(HttpMethod.Get, url); + req.Headers.Accept.Clear(); + req.Headers.Accept.ParseAdd("text/event-stream"); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + long tx = 0, rx = 0, ctx = 0, crx = 0;// = mon.GetDiff(0, 0); + + try + { + + + using var resp = await http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); + resp.EnsureSuccessStatusCode(); + + await Task.Delay(1000); + + (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + Console.WriteLine($"Handshake {ctx}/{crx}"); + + onOpen?.Invoke(); + + using var stream = await resp.Content.ReadAsStreamAsync(ct).ConfigureAwait(false); + using var reader = new System.IO.StreamReader(stream, Encoding.UTF8); + + var dataBuilder = new StringBuilder(); + + + + long totalRxBytes = 0; + + while (!ct.IsCancellationRequested) + { + var readTask = reader.ReadLineAsync(); + var completed = await Task.WhenAny(readTask, Task.Delay(Timeout.InfiniteTimeSpan, ct)).ConfigureAwait(false); + if (completed != readTask) + break; // cancelled + + var line = await readTask!; // safe because completed + if (line is null) + break; // stream ended + + if (line.Length == 0) + { + // dispatch event + if (dataBuilder.Length > 0) + { + // Remove trailing newline added while parsing + if (dataBuilder.Length > 0 && dataBuilder[dataBuilder.Length - 1] == '\n') + dataBuilder.Length--; + + var data = dataBuilder.ToString(); + onMessage?.Invoke(data); + dataBuilder.Clear(); + } + continue; + } + + // comments start with ':' -> ignore + if (line[0] == ':') + continue; + + // data: lines (may be multi-line) + if (line.StartsWith("data:")) + { + var payload = line.Length > 5 ? line.Substring(5) : string.Empty; + // If the payload starts with a single space per SSE spec, trim one leading space + if (payload.Length > 0 && payload[0] == ' ') payload = payload.Substring(1); + dataBuilder.Append(payload); + dataBuilder.Append('\n'); + } + // other fields (event:, id:, retry:) are ignored by this simple client + } + } + catch (OperationCanceledException) + { + // cancellation requested by caller + } + catch (Exception ex) + { + onError?.Invoke(ex); + } + + await Task.Delay(2000); + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + + Console.WriteLine($"Results {ctx}/{crx} Total: {tx}/{rx}"); + + } + + static string BuildUrl(string baseUrl, SseOptions opts) + { + var sb = new StringBuilder(); + sb.Append(baseUrl); + var sep = baseUrl.Contains('?') ? '&' : '?'; + sb.Append(sep); + sb.Append("messagesPerBurst=").Append(opts.MessagesPerBurst); + sb.Append("&messageSize=").Append(opts.MessageSize); + sb.Append("&intervalMs=").Append(opts.IntervalMs); + sb.Append("&burstIntervalMs=").Append(opts.BurstIntervalMs); + return sb.ToString(); + } +} + +public class SseOptions +{ + public int MessagesPerBurst { get; set; } = 1; + public int MessageSize { get; set; } = 100; + public int IntervalMs { get; set; } = 0; + public int BurstIntervalMs { get; set; } = 1000; +} diff --git a/Tests/RPC/Client/Tests/Events/Websockets.cs b/Tests/RPC/Client/Tests/Events/Websockets.cs new file mode 100644 index 0000000..703bc93 --- /dev/null +++ b/Tests/RPC/Client/Tests/Events/Websockets.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; + +namespace RPC.Client.Tests.Events +{ + public class Websockets + { + + public record BenchmarkResult(int? Requested, int Received, long TotalBytes, long DurationMs, double MessagesPerSec, double BytesPerSec); + + public static class WSClient + { + public static async Task DoTest( + string url, + int? count = 100, + int size = 128, + int intervalMs = 1000, + bool binary = true, + bool useQuery = true, + CancellationToken cancellationToken = default) + { + + Console.WriteLine("Starting Websockets benchmark..."); + // prepare connect url + var connectUrl = url; + if (useQuery) + { + var qs = new QueryBuilder(); + if (count.HasValue) qs.Add("count", count.Value.ToString()); + qs.Add("size", size.ToString()); + qs.Add("intervalMs", intervalMs.ToString()); + qs.Add("binary", binary.ToString().ToLowerInvariant()); + connectUrl += (url.Contains('?') ? "&" : "?") + qs.ToString(); + } + await Task.Delay(2000); + + using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); + mon.Start(); + + using var client = new ClientWebSocket(); + await client.ConnectAsync(new Uri(connectUrl), cancellationToken); + + // if not using query, send init JSON + if (!useQuery) + { + var init = JsonSerializer.Serialize(new { count, size, intervalMs, binary }); + var initBytes = Encoding.UTF8.GetBytes(init); + await client.SendAsync(new ArraySegment(initBytes), WebSocketMessageType.Text, true, cancellationToken); + } + + var bufferSize = Math.Max(8192, size + 4096); + var buffer = new byte[bufferSize]; + + int received = 0; + long totalBytes = 0; + long firstMs = 0; + long lastMs = 0; + + await Task.Delay(2000); + + + var (tx, rx, ctx, crx) = mon.GetDiff(0, 0); + + Console.WriteLine($"Handshake {ctx}/{crx}"); + + long totalRxBytes = 0; + + try + { + while (client.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested) + { + if (count.HasValue && received >= count.Value) break; + + // Receive a full message (handle fragmentation) + int messageBytes = 0; + WebSocketReceiveResult result; + do + { + result = await client.ReceiveAsync(new ArraySegment(buffer), cancellationToken); + + //(tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + //totalRxBytes += crx; + + if (result.MessageType == WebSocketMessageType.Close) goto EndReceive; + messageBytes += result.Count; + + } while (!result.EndOfMessage); + + var now = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; + if (received == 0) firstMs = now; + lastMs = now; + + received++; + totalBytes += messageBytes; + + if (count.HasValue && received >= count.Value) break; + } + } + catch (OperationCanceledException) { /* cancelled by caller */ } + catch (WebSocketException) { /* network error */ } + + EndReceive: + if (client.State == WebSocketState.Open || client.State == WebSocketState.CloseReceived) + { + try { await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client closing", CancellationToken.None); } catch { } + } + + var durationMs = (firstMs != 0 && lastMs >= firstMs) ? (lastMs - firstMs) : 0; + var msgsPerSec = durationMs > 0 ? (received * 1000.0) / durationMs : (double)received; + var bytesPerSec = durationMs > 0 ? (totalBytes * 1000.0) / durationMs : (double)totalBytes; + + + Console.WriteLine("Total RX bytes (monitor): " + totalRxBytes); + + await Task.Delay(2000); + + (tx, rx, ctx, crx) = mon.GetDiff(tx, rx); + + Console.WriteLine($"Total Mon {tx}/{rx} {ctx}/{crx} {received}"); + + mon.Stop(); + return new BenchmarkResult(count, received, totalBytes, durationMs, msgsPerSec, bytesPerSec); + } + + // minimal QueryString builder to avoid extra deps + private class QueryBuilder + { + private readonly StringBuilder _sb = new(); + private bool _first = true; + public void Add(string name, string value) + { + if (!_first) _sb.Append('&'); + _first = false; + _sb.Append(Uri.EscapeDataString(name)); + _sb.Append('='); + _sb.Append(Uri.EscapeDataString(value)); + } + public override string ToString() => _sb.ToString(); + } + } + } +} diff --git a/Tests/RPC/Client/Tests/Monitor.cs b/Tests/RPC/Client/Tests/Monitor.cs new file mode 100644 index 0000000..7b51eab --- /dev/null +++ b/Tests/RPC/Client/Tests/Monitor.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Diagnostics.Tracing; +using Microsoft.Diagnostics.Tracing.Parsers; +using Microsoft.Diagnostics.Tracing.Session; + +namespace RPC.Client.Tests; + +public class PerProcessNetMonitor : IDisposable +{ + private readonly int _pid; + private TraceEventSession _session; + private Task _listenTask; + private long _txBytes; + private long _rxBytes; + private volatile bool _running; + + public PerProcessNetMonitor(int pid) + { + _pid = pid; + } + + public void Start() + { + // Use a unique session name + string sessionName = "NetMon_" + Guid.NewGuid(); + _session = new TraceEventSession(sessionName); + + // Enable kernel network provider + _session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP); + + _running = true; + _listenTask = Task.Run(() => + { + _session.Source.Kernel.TcpIpRecv += evt => + { + if (evt.ProcessID == _pid) + Interlocked.Add(ref _rxBytes, evt.size); + }; + + _session.Source.Kernel.TcpIpSend += evt => + { + if (evt.ProcessID == _pid) + Interlocked.Add(ref _txBytes, evt.size); + }; + + // For UDP: + _session.Source.Kernel.UdpIpRecv += evt => + { + if (evt.ProcessID == _pid) + Interlocked.Add(ref _rxBytes, evt.size); + }; + + _session.Source.Kernel.UdpIpSend += evt => + { + if (evt.ProcessID == _pid) + Interlocked.Add(ref _txBytes, evt.size); + }; + + _session.Source.Process(); + }); + } + + public (long tx, long rx) GetTotals() + => (Interlocked.Read(ref _txBytes), Interlocked.Read(ref _rxBytes)); + + public (long tx, long rx, long diffTX, long diffRX) GetDiff(long previousTX, long previousRX) + { + var ctx = Interlocked.Read(ref _txBytes); + var crx = Interlocked.Read(ref _rxBytes); + + return (ctx, crx, ctx - previousTX, crx - previousRX); + } + + public void Stop() + { + _running = false; + _session?.Dispose(); + } + + public void Dispose() => Stop(); +} diff --git a/Tests/RPC/Client/Tests/Queue/QueueTest.cs b/Tests/RPC/Client/Tests/Queue/QueueTest.cs new file mode 100644 index 0000000..2b339f4 --- /dev/null +++ b/Tests/RPC/Client/Tests/Queue/QueueTest.cs @@ -0,0 +1,352 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace RPC.Client.Tests.Queue; + +using Esiur.Core; +using System; +using System.Collections.Generic; +using System.Linq; + + +public static class EsiurQueueEval +{ + + public static class EvalPrinter + { + public static void Print(EsiurQueueEval.EvalResult r) + { + Console.WriteLine("=== Evaluation Result ==="); + Console.WriteLine($"α (HasResource probability): {r.Alpha:F3}"); + Console.WriteLine($"λ̂ (effective arrival rate): {r.LambdaEventsPerSecond:F2} events/s"); + Console.WriteLine(); + + PrintLatencyTable(r.Latency); + + Console.WriteLine(); + PrintValidation(r.Validation); + + if (r.FlushSizeStats != null) + { + Console.WriteLine(); + PrintStats("Flush size (≤ window)", r.FlushSizeStats); + } + } + + private static void PrintLatencyTable(EsiurQueueEval.LatencyDecomposition l) + { + Console.WriteLine("Latency Decomposition (ms)"); + Console.WriteLine("-----------------------------------------------"); + Console.WriteLine($"{"Metric",-16} {"Mean",8} {"P50",8} {"P95",8} {"P99",8} {"Max",8}"); + Console.WriteLine("-----------------------------------------------"); + + PrintRow("Readiness R", l.ReadinessMs); + PrintRow("HOL Δ", l.HolMs); + PrintRow("End-to-End D", l.EndToEndMs); + + Console.WriteLine("-----------------------------------------------"); + } + + private static void PrintValidation(EsiurQueueEval.ModelValidation v) + { + Console.WriteLine("Resequencing Model Validation"); + Console.WriteLine("-----------------------------------------------"); + Console.WriteLine("Absolute error |d − d̂| (ms)"); + PrintStats("Error", v.AbsErrorMs); + + if (v.MaxNegativeSlackMs > 0) + { + Console.WriteLine($"Max negative slack (delivered earlier than model): {v.MaxNegativeSlackMs:F4} ms"); + } + else + { + Console.WriteLine("No negative slack observed (model is conservative)."); + } + } + + private static void PrintRow(string name, EsiurQueueEval.Stats s) + { + Console.WriteLine( + $"{name,-16} " + + $"{s.Mean,8:F2} " + + $"{s.P50,8:F2} " + + $"{s.P95,8:F2} " + + $"{s.P99,8:F2} " + + $"{s.Max,8:F2}" + ); + } + + private static void PrintStats(string name, EsiurQueueEval.Stats s) + { + Console.WriteLine( + $"{name,-20} " + + $"mean={s.Mean,8:F02} " + + $"p50={s.P50,8:F02} " + + $"p95={s.P95,8:F02} " + + $"p99={s.P99,8:F02} " + + $"max={s.Max,8:F02}" + ); + } + } + + public sealed record Stats(double Mean, double P50, double P95, double P99, double Max); + + public sealed record LatencyDecomposition(Stats ReadinessMs, Stats HolMs, Stats EndToEndMs); + + public sealed record ModelValidation( + Stats AbsErrorMs, + double MaxNegativeSlackMs, // worst case where Delivered < predicted (if happens) + int Count); + + public sealed record EvalResult( + double Alpha, + double LambdaEventsPerSecond, + double MuEventsPerSecond, // <-- NEW + LatencyDecomposition Latency, + ModelValidation Validation, + Stats QueueLength, + Stats? FlushSizeStats); + + /// + /// Evaluates Esiur fork-join readiness + in-order resequencing using in-memory items. + /// Assumes items refer to a single ordered stream (per resource queue). + /// + public static EvalResult Evaluate( + IReadOnlyList> items, + double flushWindowMs = 0.5, + bool computeFlush = true) + { + if (items == null) throw new ArgumentNullException(nameof(items)); + if (items.Count == 0) throw new ArgumentException("items is empty."); + + // Ensure deterministic order: prefer Sequence, then Arrival timestamp + var ordered = items + .OrderBy(x => x.Sequence) + .ThenBy(x => x.Arrival) + .ToArray(); + + int n = ordered.Length; + + // Latency components in milliseconds + var readiness = new double[n]; // R = r-a + var hol = new double[n]; // Δ = d-r + var endToEnd = new double[n]; // D = d-a + + int resCount = 0; + for (int i = 0; i < n; i++) + { + var e = ordered[i]; + + double Rms = (e.Ready - e.Arrival).TotalMilliseconds; + double Hms = (e.Delivered - e.Ready).TotalMilliseconds; + double Dms = (e.Delivered - e.Arrival).TotalMilliseconds; + + // Robustness against logging placement or clock issues + if (Rms < 0) Rms = 0; + if (Hms < 0) Hms = 0; + if (Dms < 0) Dms = 0; + + readiness[i] = Rms; + hol[i] = Hms; + endToEnd[i] = Dms; + + if (e.HasResource) resCount++; + } + + // α = P(HasResource) + double alpha = (double)resCount / n; + + + // Effective arrival rate λ̂ from arrival timeline + double lambda = EstimateLambda(ordered); + + // Effective departure / readiness rate μ̂ from delivery timeline + double mu = EstimateMu(ordered); + + var latency = new LatencyDecomposition( + ReadinessMs: ComputeStats(readiness), + HolMs: ComputeStats(hol), + EndToEndMs: ComputeStats(endToEnd)); + + // --- Resequencing validation: d_hat_i = max(r_i, d_hat_{i-1}) --- + // Use DateTime ticks for exactness, then convert to ms. + var absErrMs = new double[n]; + long prevPredictedTicks = long.MinValue; + double maxNegativeSlackMs = 0; + + for (int i = 0; i < n; i++) + { + long ri = ordered[i].Ready.Ticks; + + long predicted = (i == 0) + ? ri + : Math.Max(ri, prevPredictedTicks); + + prevPredictedTicks = predicted; + + long observed = ordered[i].Delivered.Ticks; + long errTicks = Math.Abs(observed - predicted); + absErrMs[i] = TicksToMs(errTicks); + + // If observed delivery occurs earlier than model predicts (shouldn't, but track it) + long slackTicks = observed - predicted; // negative => earlier than predicted + if (slackTicks < 0) + { + double slackMs = TicksToMs(-slackTicks); + if (slackMs > maxNegativeSlackMs) maxNegativeSlackMs = slackMs; + } + } + + var validation = new ModelValidation( + AbsErrorMs: ComputeStats(absErrMs), + MaxNegativeSlackMs: maxNegativeSlackMs, + Count: n); + + // --- Flush sizes (optional): consecutive deliveries within window --- + //Stats? flushStats = null; + //if (computeFlush) + //{ + // var flushSizes = ComputeFlushSizes(ordered, flushWindowMs); + // flushStats = ComputeStats(flushSizes.Select(x => (double)x).ToArray()); + //} + + var queueLength = ComputeStats(ordered.Select(x => (double)x.NotificationsCountWaitingInTheQueueAtEnqueueing).ToArray()); + + var flushStats = ComputeStats(ordered.GroupBy(x => x.FlushId).Select(x => (double)x.First().BatchSize).ToArray()); + + return new EvalResult(alpha, lambda, mu, latency, validation, queueLength, flushStats); + } + + // ---------------- Helpers ---------------- + + private static double EstimateLambda(AsyncQueueItem[] ordered) + { + if (ordered.Length < 2) return 0; + + DateTime first = ordered[0].Arrival; + DateTime last = ordered[^1].Arrival; + double seconds = (last - first).TotalSeconds; + if (seconds <= 0) return 0; + + // N-1 arrivals over observed interval + return (ordered.Length - 1) / seconds; + } + + private static double TicksToMs(long ticks) => ticks / 10_000.0; // 1 tick = 100ns + + private static int[] ComputeFlushSizes(AsyncQueueItem[] ordered, double windowMs) + { + var sizes = new List(ordered.Length); + long windowTicks = (long)(windowMs * 10_000.0); + + int i = 0; + while (i < ordered.Length) + { + int j = i + 1; + long baseD = ordered[i].Delivered.Ticks; + + while (j < ordered.Length) + { + long dj = ordered[j].Delivered.Ticks; + if (Math.Abs(dj - baseD) <= windowTicks) j++; + else break; + } + + sizes.Add(j - i); + i = j; + } + + return sizes.ToArray(); + } + + private static Stats ComputeStats(double[] values) + { + if (values.Length == 0) return new Stats(0, 0, 0, 0, 0); + + double mean = values.Average(); + double max = values.Max(); + + var sorted = (double[])values.Clone(); + Array.Sort(sorted); + + return new Stats( + Mean: mean, + P50: QuantileSorted(sorted, 0.50), + P95: QuantileSorted(sorted, 0.95), + P99: QuantileSorted(sorted, 0.99), + Max: max); + } + + // Linear interpolation quantile + private static double QuantileSorted(double[] sorted, double q) + { + if (sorted.Length == 1) return sorted[0]; + + double pos = (sorted.Length - 1) * q; + int lo = (int)Math.Floor(pos); + int hi = (int)Math.Ceiling(pos); + if (lo == hi) return sorted[lo]; + + double frac = pos - lo; + return sorted[lo] + (sorted[hi] - sorted[lo]) * frac; + } + + // Compute the element-wise average of a sequence of EvalResult + public static EvalResult Average(IEnumerable results) + { + if (results == null) throw new ArgumentNullException(nameof(results)); + var arr = results.ToArray(); + if (arr.Length == 0) throw new ArgumentException("results is empty.", nameof(results)); + + double avgAlpha = arr.Average(r => r.Alpha); + double avgLambda = arr.Average(r => r.LambdaEventsPerSecond); + double avgMu = arr.Average(r => r.MuEventsPerSecond); + + Stats avgReadiness = AverageStats(arr.Select(r => r.Latency.ReadinessMs)); + Stats avgHol = AverageStats(arr.Select(r => r.Latency.HolMs)); + Stats avgE2E = AverageStats(arr.Select(r => r.Latency.EndToEndMs)); + + var avgLatency = new LatencyDecomposition(avgReadiness, avgHol, avgE2E); + + Stats avgAbsError = AverageStats(arr.Select(r => r.Validation.AbsErrorMs)); + double worstNegativeSlack = arr.Max(r => r.Validation.MaxNegativeSlackMs); + int totalCount = arr.Sum(r => r.Validation.Count); + + var avgValidation = new ModelValidation(avgAbsError, worstNegativeSlack, totalCount); + + Stats? avgFlush = null; + var flushStatsSeq = arr.Select(r => r.FlushSizeStats).Where(s => s != null).Select(s => s!).ToArray(); + if (flushStatsSeq.Length > 0) avgFlush = AverageStats(flushStatsSeq); + + + var avgQueue = AverageStats(arr.Select(x => x.QueueLength)); + + return new EvalResult(avgAlpha, avgLambda, avgMu, avgLatency, avgValidation, avgQueue, avgFlush); + } + + private static double EstimateMu(AsyncQueueItem[] ordered) + { + if (ordered.Length < 2) return 0; + + DateTime first = ordered[0].Delivered; + DateTime last = ordered[^1].Delivered; + double seconds = (last - first).TotalSeconds; + if (seconds <= 0) return 0; + + // N-1 completions over observed interval + return (ordered.Length - 1) / seconds; + } + + private static Stats AverageStats(IEnumerable seq) + { + var arr = seq.ToArray(); + if (arr.Length == 0) return new Stats(0, 0, 0, 0, 0); + return new Stats( + Mean: arr.Average(s => s.Mean), + P50: arr.Average(s => s.P50), + P95: arr.Average(s => s.P95), + P99: arr.Average(s => s.P99), + Max: arr.Average(s => s.Max)); + } +} diff --git a/Tests/RPC/Client/Tests/Shared.cs b/Tests/RPC/Client/Tests/Shared.cs new file mode 100644 index 0000000..55c1289 --- /dev/null +++ b/Tests/RPC/Client/Tests/Shared.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RPC.Client.Tests +{ + internal class Shared + { + static Random rng = new Random(24241564); + + // Generate random int array of given length and distribution + public static int[] GenerateInt32(int length, string pattern = "uniform", + int range = int.MaxValue) + { + + var data = new int[length]; + + switch (pattern.ToLower()) + { + case "uniform": + // Random values in [-range, range] + for (int i = 0; i < length; i++) + data[i] = rng.Next(-range, range); + break; + + case "positive": + for (int i = 0; i < length; i++) + data[i] = rng.Next(0, range); + break; + + case "negative": + for (int i = 0; i < length; i++) + data[i] = -rng.Next(0, range); + break; + + case "alternating": + for (int i = 0; i < length; i++) + { + int val = rng.Next(0, range); + data[i] = (i % 2 == 0) ? val : -val; + } + break; + + case "small": + // Focused on small magnitudes to test ZigZag fast path + for (int i = 0; i < length; i++) + data[i] = rng.Next(-64, 65); + break; + + + case "ascending": + { + int start = rng.Next(-range, range); + for (int i = 0; i < length; i++) + data[i] = start + i; + } + break; + + default: + throw new ArgumentException($"Unknown pattern: {pattern}"); + } + + return data; + } + + public static Dictionary BuildBytesWorkLoads(int seed = 1000) + { + var result = new Dictionary(); + + var r = new Random(seed); + + + // Small + { + var small = new byte[100]; + r.NextBytes(small); + result.Add("Small", small); + } + + // Medium + { + var medium = new byte[1000]; + r.NextBytes(medium); + result.Add("Medium", medium); + } + + // Large + { + var large = new byte[1000000]; + r.NextBytes(large); + result.Add("Large", large); + } + + return result; + } + + + + public static Dictionary BuildIntWorkloads(int seed = 1000) + { + var result = new Dictionary(); + var r = new Random(seed); + + result.Add("uniform", GenerateInt32(1000, "uniform")); + result.Add("small", GenerateInt32(1000, "small")); + result.Add("alternating", GenerateInt32(1000, "alternating")); + result.Add("ascending", GenerateInt32(1000, "ascending")); + + + return result; + } + + + } +} diff --git a/Tests/RPC/Client/Tests/TestResults.cs b/Tests/RPC/Client/Tests/TestResults.cs new file mode 100644 index 0000000..297d28c --- /dev/null +++ b/Tests/RPC/Client/Tests/TestResults.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace RPC.Client.Tests +{ + public class TestResults + { + public Dictionary Docs { get; set; } = new(); + public Dictionary Bytes { get; set; } = new(); + public Dictionary Ints { get; set; } = new(); + + } +} diff --git a/Tests/RPC/Esiur/EchoModel.cs b/Tests/RPC/Esiur/EchoModel.cs new file mode 100644 index 0000000..3ffe679 --- /dev/null +++ b/Tests/RPC/Esiur/EchoModel.cs @@ -0,0 +1,208 @@ +#nullable enable + +using Esiur.Data; +using Esiur.Resource; +using System; +using System.Collections.Generic; + +namespace Esiur.Tests.RPC.EsiurServer +{ + // ====================== Enums ====================== + + [Export] + public enum Currency + { + IQD, + CNH, + USD, + EUR, + JPY, + GBP + } + + [Export] + public enum DocType + { + Quote, + Order, + Invoice, + CreditNote + } + + [Export] + public enum PaymentMethod + { + Cash, + Card, + Wire, + Crypto, + Other + } + + [Export] + public enum LineType + { + Product, + Service, + Discount, + Shipping + } + + // Variant.Kind + [Export] + public enum Kind + { + Null, + Bool, + Int64, + UInt64, + Double, + Decimal, + String, + Bytes, + DateTime, + Guid + } + + // ====================== Variant & Entry helpers ====================== + [Export] + public sealed class Variant:IRecord + { + public Kind Tag { get; set; } + + public bool? Bool { get; set; } + public long? I64 { get; set; } + public ulong? U64 { get; set; } + public double? F64 { get; set; } + public string? Str { get; set; } + public byte[]? Bytes { get; set; } + public DateTime? Dt { get; set; } + public byte[]? Guid { get; set; } + } + + [Export] + public sealed class MetaEntry:IRecord + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + [Export] + public sealed class ExtEntry:IRecord + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + // ====================== Party & Address ====================== + [Export] + public sealed class Address:IRecord + { + public string Line1 { get; set; } = string.Empty; + public string? Line2 { get; set; } + + public string City { get; set; } = string.Empty; + public string Region { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string? PostalCode { get; set; } + } + + [Export] + public sealed class Party:IRecord + { + public ulong Id { get; set; } + + public string Name { get; set; } = string.Empty; + public string? TaxId { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + + public Address? Address { get; set; } + + public string? PreferredLanguage { get; set; } + } + + // ====================== DocumentHeader ====================== + + [Export] + public sealed class DocumentHeader:IRecord + { + // Guid serialized as bytes + public byte[] DocId { get; set; } = Array.Empty(); + + public DocType Type { get; set; } + public int Version { get; set; } + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + + public Currency Currency { get; set; } + + public string? Notes { get; set; } + + // corresponds to Dictionary + public Dictionary Meta { get; set; } = new(); + } + + // ====================== LineItem, Payment, Attachment ====================== + + [Export] + public sealed class LineItem:IRecord + { + public int LineNo { get; set; } + public LineType Type { get; set; } + + public string SKU { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + + public double Qty { get; set; } + public string QtyUnit { get; set; } = string.Empty; + + public double UnitPrice { get; set; } + + public double? VatRate { get; set; } + public double? Discount { get; set; } + + // Dictionary + public Map Ext { get; set; } = new(); + } + + [Export] + public sealed class Payment:IRecord + { + public PaymentMethod Method { get; set; } + + public double Amount { get; set; } + public string? Reference { get; set; } + + public DateTime Timestamp { get; set; } + + public double? Fee { get; set; } + + public Currency Currency { get; set; } + } + + [Export] + public sealed class Attachment:IRecord + { + public string Name { get; set; } = string.Empty; + public string MimeType { get; set; } = string.Empty; + public byte[] Data { get; set; } = Array.Empty(); + } + + // ====================== Top-level BusinessDocument ====================== + [Export] + public sealed class BusinessDocument:IRecord + { + public DocumentHeader Header { get; set; } = new DocumentHeader(); + + public Party Seller { get; set; } = new Party(); + public Party Buyer { get; set; } = new Party(); + + public LineItem[] Items { get; set; } = Array.Empty(); + public Payment[] Payments { get; set; } = Array.Empty(); + public Attachment[] Attachments { get; set; } = Array.Empty(); + + public int[] RiskScores { get; set; } = Array.Empty(); + } +} diff --git a/Tests/RPC/Esiur/Esiur.Tests.RPC.EsiurServer.csproj b/Tests/RPC/Esiur/Esiur.Tests.RPC.EsiurServer.csproj new file mode 100644 index 0000000..3143391 --- /dev/null +++ b/Tests/RPC/Esiur/Esiur.Tests.RPC.EsiurServer.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/Tests/RPC/Esiur/Program.cs b/Tests/RPC/Esiur/Program.cs new file mode 100644 index 0000000..63da94f --- /dev/null +++ b/Tests/RPC/Esiur/Program.cs @@ -0,0 +1,33 @@ +// See https://aka.ms/new-console-template for more information +using Esiur.Data; +using Esiur.Protocol; +using Esiur.Proxy; +using Esiur.Resource; +using Esiur.Stores; +using Esiur.Tests.RPC.EsiurServer; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; + +ushort port = 5005; + +if (args.Count() > 0) + port = ushort.Parse(args[0]); + +Console.WriteLine($"Esiur server listening on port {port}..."); + +var wh = Warehouse.Default; +var mem = await wh.Put("sys", new MemoryStore()); +var service = await wh.Put("sys/service", new Service()); +var ds = await wh.Put("sys/server", new EpServer() { Port = port, EntryPoint = service, + AllowUnauthorizedAccess = true }); + +await wh.Open(); + + +Console.WriteLine("Open"); + +if (!Directory.Exists("template")) + Directory.CreateDirectory("template"); + +TypeDefGenerator.GetTypes("ep://localhost:5005/sys/service", "template"); \ No newline at end of file diff --git a/Tests/RPC/Esiur/Properties/PublishProfiles/FolderProfile.pubxml b/Tests/RPC/Esiur/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..050e099 --- /dev/null +++ b/Tests/RPC/Esiur/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,11 @@ + + + + + Release + Any CPU + bin\Release\net10.0\publish\ + FileSystem + <_TargetId>Folder + + \ No newline at end of file diff --git a/Tests/RPC/Esiur/Service.cs b/Tests/RPC/Esiur/Service.cs new file mode 100644 index 0000000..fa60117 --- /dev/null +++ b/Tests/RPC/Esiur/Service.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Esiur.Core; +using Esiur.Data; +using Esiur.Protocol; +using Esiur.Resource; + +namespace Esiur.Tests.RPC.EsiurServer +{ + [Resource] + public partial class Service : EntryPoint + { + + public static bool[] GenerateRandomBoolSequence( + int length, + double probabilityTrue, + Random? rng = null) + { + if (length <= 0) + throw new ArgumentOutOfRangeException(nameof(length)); + + if (probabilityTrue < 0.0 || probabilityTrue > 1.0) + throw new ArgumentOutOfRangeException(nameof(probabilityTrue)); + + rng ??= Random.Shared; + + int trueTarget = (int)Math.Round(length * probabilityTrue); + int remaining = length; + int remainingTrue = trueTarget; + + var result = new bool[length]; + + for (int i = 0; i < length; i++) + { + // Probability adjusted to guarantee exact total + double p = (double)remainingTrue / remaining; + bool value = rng.NextDouble() < p; + + result[i] = value; + + if (value) + remainingTrue--; + + remaining--; + } + + return result; + } + public List TestObjects = new List(); + + [Export] + public event ResourceEventHandler MessageUpdated; + + [Export] + + public byte[] messageToChange; + + [Export] + public object testProperty; + + // ---------- Unary: scalars & bytes ---------- + [Export] + public byte[] EchoBytes(byte[] payload) + => payload; + [Export] + + public BusinessDocument[] EchoDocuments(BusinessDocument[] payload) + => payload; + [Export] + + public int[] EchoIntArray(int[] payload) + => payload; + [Export] + + public string[] EchoStringArray(string[] payload) + => payload; + [Export] + + public Map EchoMap(Map payload) + => payload; + [Export] + + public DocType[] EchoEnumArray(DocType[] payload) + => payload; + + [Export] + + public AsyncReply ChunkTest(int count, int size, int delay) + { + var rt = new AsyncReply(); + + + Task.Run(async () => + { + await Task.Delay(3000); + + for (int i = 0; i < count; i++) + { + byte[] chunk = new byte[size]; + new Random().NextBytes(chunk); + rt.TriggerChunk(chunk); + await Task.Delay(delay); + } + + rt.Trigger(new byte[0]); + }); + + return rt; + } + + + [Export] + public async void PropertyChangeTest(int count, int size, int delay) + { + await Task.Delay(3000); + + for (int i = 0; i < count; i++) + { + byte[] chunk = new byte[size]; + new Random().NextBytes(chunk); + + MessageToChange = chunk; + await Task.Delay(delay); + } + } + + [Export] + public async void EventTest(int count, int size, int delay) + { + await Task.Delay(3000); + + for (int i = 0; i < count; i++) + { + byte[] chunk = new byte[size]; + new Random().NextBytes(chunk); + + MessageUpdated?.Invoke(chunk); + await Task.Delay(delay); + } + } + + + static Random rand = new Random(322221); + + [Export] + public async AsyncReply StartUpdatesLocal(int interval, int count, double localProbability) + { + + var dis = GenerateRandomBoolSequence(count, localProbability, new Random(2222)); + + for (var i = 0; i < count; i++) + { + //var probability = rand.NextDouble(); + + if (dis[i])// probability <= localProbability) + { + var o = await Warehouse.Default.New("sys/anything"); + + o.Value = i; + o.Name = "Update " + i; + + TestObjects.Add(o); + + TestProperty = o; + } + else + { + TestProperty = i; + } + + await Task.Delay(interval); + + } + + return null; + } + + [Export] + public async AsyncReply> StartUpdatesRemote(int interval, int count, double remoteProbability, string remoteLink) + { + for (var i = 0; i < count; i++) + { + var probability = rand.NextDouble(); + + if (probability <= remoteProbability) + { + TestProperty = remoteLink; + } + else + { + TestProperty = i; + } + + await Task.Delay(interval); + + } + + return null; + } + + + [Export] + public async AsyncReply StartUpdatesMirror(int interval, int count, double remoteProbability, string remoteNode, string remoteLink) + { + + var remoteCon = await Warehouse.Default.Get(remoteNode); + + for (var i = 0; i < count; i++) + { + var probability = rand.NextDouble(); + + if (probability <= remoteProbability) + { + var o = await remoteCon.Get(remoteLink); + TestObjects.Add(o as TestObject); + + TestProperty = o; + } + else + { + TestProperty = i; + } + + await Task.Delay(interval); + + } + + return null; + } + + + + [Export] + public async AsyncReply> StartUpdates(int interval, int count, double localProbability, double remoteProbability, string remoteHostLink) + { + + //var created = new List(); + + //for (var i = 0; i < count; i++) + //{ + // var o = await Warehouse.Default.New("sys/anything"); + // o.Value = i; + // o.Name = "Update " + i; + // created.Add(o); + //} + + for (var i = 0; i < count; i++) + { + + //TestProperty = created[rand.Next(999)]; + //await Task.Delay(interval); + + // Console.WriteLine("Updating " + i); + var probability = rand.NextDouble(); + + if ((localProbability != 0 && probability <= localProbability) || localProbability == 1) + { + var o = await Warehouse.Default.New("sys/anything"); + + o.Value = i; + o.Name = "Update " + i; + + TestObjects.Add(o); + + TestProperty = o; + } + else if (probability < localProbability + remoteProbability) + { + TestProperty = new ResourceLink(remoteHostLink); + } + else + { + TestProperty = i; + } + + await Task.Delay(interval); + } + + TestObjects.Clear(); + + return null; + } + + public override async AsyncReply Query(string path, EpConnection sender) + { + if (path == "gen") + { + var o = await Warehouse.Default.New("sys/anything"); + o.Value = rand.Next(); + o.Name = "Update " + o.Value; + TestObjects.Add(o); + return o; + } + else + { + if (this.Instance != null) + return await this.Instance.Warehouse.Query(path); + else + return null; + } + } + + protected override bool Create() + { + return true; + } + } +} diff --git a/Tests/RPC/Esiur/TestObject.cs b/Tests/RPC/Esiur/TestObject.cs new file mode 100644 index 0000000..22ae19f --- /dev/null +++ b/Tests/RPC/Esiur/TestObject.cs @@ -0,0 +1,15 @@ +using Esiur.Resource; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esiur.Tests.RPC.EsiurServer +{ + [Resource] + public partial class TestObject + { + [Export] int size; + [Export] string name; + [Export] object value; + } +} diff --git a/Tests/RPC/Json/EchoModel.cs b/Tests/RPC/Json/EchoModel.cs new file mode 100644 index 0000000..69e9d21 --- /dev/null +++ b/Tests/RPC/Json/EchoModel.cs @@ -0,0 +1,194 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Esiur.Tests.RPC.JsonServer +{ + // ====================== Enums ====================== + + public enum Currency + { + IQD, + CNH, + USD, + EUR, + JPY, + GBP + } + + public enum DocType + { + Quote, + Order, + Invoice, + CreditNote + } + + public enum PaymentMethod + { + Cash, + Card, + Wire, + Crypto, + Other + } + + public enum LineType + { + Product, + Service, + Discount, + Shipping + } + + // Variant.Kind + public enum Kind + { + Null, + Bool, + Int64, + UInt64, + Double, + Decimal, + String, + Bytes, + DateTime, + Guid + } + + // ====================== Variant & Entry helpers ====================== + + public sealed class Variant + { + public Kind Tag { get; set; } + + public bool? Bool { get; set; } + public long? I64 { get; set; } + public ulong? U64 { get; set; } + public double? F64 { get; set; } + public string? Str { get; set; } + public byte[]? Bytes { get; set; } + public DateTime? Dt { get; set; } + public byte[]? Guid { get; set; } + } + + public sealed class MetaEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + public sealed class ExtEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + // ====================== Party & Address ====================== + + public sealed class Address + { + public string Line1 { get; set; } = string.Empty; + public string? Line2 { get; set; } + + public string City { get; set; } = string.Empty; + public string Region { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string? PostalCode { get; set; } + } + + public sealed class Party + { + public ulong Id { get; set; } + + public string Name { get; set; } = string.Empty; + public string? TaxId { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + + public Address? Address { get; set; } + + public string? PreferredLanguage { get; set; } + } + + // ====================== DocumentHeader ====================== + + public sealed class DocumentHeader + { + // Guid serialized as bytes + public byte[] DocId { get; set; } = Array.Empty(); + + public DocType Type { get; set; } + public int Version { get; set; } + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + + public Currency Currency { get; set; } + + public string? Notes { get; set; } + + // corresponds to Dictionary + public Dictionary Meta { get; set; } = new(); + } + + // ====================== LineItem, Payment, Attachment ====================== + + public sealed class LineItem + { + public int LineNo { get; set; } + public LineType Type { get; set; } + + public string SKU { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + + public double Qty { get; set; } + public string QtyUnit { get; set; } = string.Empty; + + public double UnitPrice { get; set; } + + public double? VatRate { get; set; } + public double? Discount { get; set; } + + // Dictionary + public Dictionary Ext { get; set; } = new(); + } + + public sealed class Payment + { + public PaymentMethod Method { get; set; } + + public double Amount { get; set; } + public string? Reference { get; set; } + + public DateTime Timestamp { get; set; } + + public double? Fee { get; set; } + + public Currency Currency { get; set; } + } + + public sealed class Attachment + { + public string Name { get; set; } = string.Empty; + public string MimeType { get; set; } = string.Empty; + public byte[] Data { get; set; } = Array.Empty(); + } + + // ====================== Top-level BusinessDocument ====================== + + public sealed class BusinessDocument + { + public DocumentHeader Header { get; set; } = new DocumentHeader(); + + public Party Seller { get; set; } = new Party(); + public Party Buyer { get; set; } = new Party(); + + public LineItem[] Items { get; set; } = Array.Empty(); + public Payment[] Payments { get; set; } = Array.Empty(); + public Attachment[] Attachments { get; set; } = Array.Empty(); + + public int[] RiskScores { get; set; } = Array.Empty(); + } +} diff --git a/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.csproj b/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.csproj new file mode 100644 index 0000000..cdbe272 --- /dev/null +++ b/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + + diff --git a/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.http b/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.http new file mode 100644 index 0000000..91820ba --- /dev/null +++ b/Tests/RPC/Json/Esiur.Tests.RPC.JsonServer.http @@ -0,0 +1,6 @@ +@RPC.JSON_HostAddress = http://localhost:5100 + +GET {{RPC.JSON_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Tests/RPC/Json/Program.cs b/Tests/RPC/Json/Program.cs new file mode 100644 index 0000000..b1a0524 --- /dev/null +++ b/Tests/RPC/Json/Program.cs @@ -0,0 +1,40 @@ +// Echo.JsonRpc/Program.cs (Server) +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; +using Esiur.Tests.RPC.JsonServer; +using System.Text.Json; +using System.Text.Json.Serialization; + + +var app = WebApplication.Create(args); +var json = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.Never }; + +app.MapPost("/rpc", async (HttpRequest req) => +{ + var rpc = await JsonSerializer.DeserializeAsync(req.Body, json); + object? result = null; + + //switch (rpc!.Method) + //{ + // case "EchoBytes": result = rpc.Params.Deserialize(json); break; + // case "EchoDocuments": result = rpc.Params!.Value.GetProperty("docs").Deserialize(json); break; + // case "EchoIntArray": result = rpc.Params!.Value.GetProperty("array").Deserialize(json); break; + // case "EchoStringArray": result = rpc.Params!.Value.GetProperty("array").Deserialize(json); break; + // case "EchoMap": result = rpc.Params!.Value.GetProperty("map").Deserialize>(json); break; + // case "EchoEnumArray": + // var arr = rpc.Params!.Value.GetProperty("docTypes").Deserialize(json)!; + // result = (arr.Length == 0) ? DocType.Quote : arr[^1]; + // break; + // default: return Results.BadRequest(); + //} + + return Results.Json(new JsonRpcRes { Jsonrpc = "2.0", Id = rpc.Id, Result = rpc.Params }, json); +}); + +app.Urls.Add("http://0.0.0.0:5100"); + +app.Run(); + +record JsonRpcReq(string Jsonrpc, string Method, object Params, string Id); +record JsonRpcRes { public string Jsonrpc { get; init; } = "2.0"; public string Id { get; init; } = "1"; public object? Result { get; init; } } diff --git a/Tests/RPC/Json/Properties/launchSettings.json b/Tests/RPC/Json/Properties/launchSettings.json new file mode 100644 index 0000000..a500f0e --- /dev/null +++ b/Tests/RPC/Json/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5126", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7193;http://localhost:5126", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Tests/RPC/Json/appsettings.Development.json b/Tests/RPC/Json/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Tests/RPC/Json/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Tests/RPC/Json/appsettings.json b/Tests/RPC/Json/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Tests/RPC/Json/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Tests/RPC/SignalR/EchoHub.cs b/Tests/RPC/SignalR/EchoHub.cs new file mode 100644 index 0000000..9514c41 --- /dev/null +++ b/Tests/RPC/SignalR/EchoHub.cs @@ -0,0 +1,13 @@ +// Echo.SignalR/EchoHub.cs +using Microsoft.AspNetCore.SignalR; +namespace Esiur.Tests.RPC.SignalRServer; + +public class EchoHub : Hub +{ + public byte[] EchoBytes(byte[] data) => data; + public BusinessDocument[] EchoDocuments(BusinessDocument[] docs) => docs; + public int[] EchoIntArray(int[] array) => array; + public string[] EchoStringArray(string[] array) => array; + public Dictionary EchoMap(Dictionary map) => map; + public DocType EchoEnumArray(DocType[] docTypes) => docTypes.Length == 0 ? DocType.Quote : docTypes[^1]; +} diff --git a/Tests/RPC/SignalR/EchoModel.cs b/Tests/RPC/SignalR/EchoModel.cs new file mode 100644 index 0000000..d7e943e --- /dev/null +++ b/Tests/RPC/SignalR/EchoModel.cs @@ -0,0 +1,194 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Esiur.Tests.RPC.SignalRServer +{ + // ====================== Enums ====================== + + public enum Currency + { + IQD, + CNH, + USD, + EUR, + JPY, + GBP + } + + public enum DocType + { + Quote, + Order, + Invoice, + CreditNote + } + + public enum PaymentMethod + { + Cash, + Card, + Wire, + Crypto, + Other + } + + public enum LineType + { + Product, + Service, + Discount, + Shipping + } + + // Variant.Kind + public enum Kind + { + Null, + Bool, + Int64, + UInt64, + Double, + Decimal, + String, + Bytes, + DateTime, + Guid + } + + // ====================== Variant & Entry helpers ====================== + + public sealed class Variant + { + public Kind Tag { get; set; } + + public bool? Bool { get; set; } + public long? I64 { get; set; } + public ulong? U64 { get; set; } + public double? F64 { get; set; } + public string? Str { get; set; } + public byte[]? Bytes { get; set; } + public DateTime? Dt { get; set; } + public byte[]? Guid { get; set; } + } + + public sealed class MetaEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + public sealed class ExtEntry + { + public string Key { get; set; } = string.Empty; + public Variant Value { get; set; } = new Variant(); + } + + // ====================== Party & Address ====================== + + public sealed class Address + { + public string Line1 { get; set; } = string.Empty; + public string? Line2 { get; set; } + + public string City { get; set; } = string.Empty; + public string Region { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string? PostalCode { get; set; } + } + + public sealed class Party + { + public ulong Id { get; set; } + + public string Name { get; set; } = string.Empty; + public string? TaxId { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + + public Address? Address { get; set; } + + public string? PreferredLanguage { get; set; } + } + + // ====================== DocumentHeader ====================== + + public sealed class DocumentHeader + { + // Guid serialized as bytes + public byte[] DocId { get; set; } = Array.Empty(); + + public DocType Type { get; set; } + public int Version { get; set; } + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + + public Currency Currency { get; set; } + + public string? Notes { get; set; } + + // corresponds to Dictionary + public Dictionary Meta { get; set; } = new(); + } + + // ====================== LineItem, Payment, Attachment ====================== + + public sealed class LineItem + { + public int LineNo { get; set; } + public LineType Type { get; set; } + + public string SKU { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + + public double Qty { get; set; } + public string QtyUnit { get; set; } = string.Empty; + + public double UnitPrice { get; set; } + + public double? VatRate { get; set; } + public double? Discount { get; set; } + + // Dictionary + public Dictionary Ext { get; set; } = new(); + } + + public sealed class Payment + { + public PaymentMethod Method { get; set; } + + public double Amount { get; set; } + public string? Reference { get; set; } + + public DateTime Timestamp { get; set; } + + public double? Fee { get; set; } + + public Currency Currency { get; set; } + } + + public sealed class Attachment + { + public string Name { get; set; } = string.Empty; + public string MimeType { get; set; } = string.Empty; + public byte[] Data { get; set; } = Array.Empty(); + } + + // ====================== Top-level BusinessDocument ====================== + + public sealed class BusinessDocument + { + public DocumentHeader Header { get; set; } = new DocumentHeader(); + + public Party Seller { get; set; } = new Party(); + public Party Buyer { get; set; } = new Party(); + + public LineItem[] Items { get; set; } = Array.Empty(); + public Payment[] Payments { get; set; } = Array.Empty(); + public Attachment[] Attachments { get; set; } = Array.Empty(); + + public int[] RiskScores { get; set; } = Array.Empty(); + } +} diff --git a/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.csproj b/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.csproj new file mode 100644 index 0000000..ea8d545 --- /dev/null +++ b/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + + + + + + + + diff --git a/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.http b/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.http new file mode 100644 index 0000000..b664fdb --- /dev/null +++ b/Tests/RPC/SignalR/Esiur.Tests.RPC.SignalRServer.http @@ -0,0 +1,6 @@ +@RPC.SignalR_HostAddress = http://localhost:5026 + +GET {{RPC.SignalR_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Tests/RPC/SignalR/Program.cs b/Tests/RPC/SignalR/Program.cs new file mode 100644 index 0000000..18a4231 --- /dev/null +++ b/Tests/RPC/SignalR/Program.cs @@ -0,0 +1,16 @@ + +using Esiur.Tests.RPC.SignalRServer; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddSignalR(o => +{ + o.EnableDetailedErrors = true; + o.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 10 MB +}); + +var app = builder.Build(); + +app.MapHub("/hub/echo"); +app.Urls.Add("http://0.0.0.0:5200"); +app.Run(); \ No newline at end of file diff --git a/Tests/RPC/SignalR/Properties/launchSettings.json b/Tests/RPC/SignalR/Properties/launchSettings.json new file mode 100644 index 0000000..d012f05 --- /dev/null +++ b/Tests/RPC/SignalR/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5026", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7175;http://localhost:5026", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Tests/RPC/SignalR/appsettings.Development.json b/Tests/RPC/SignalR/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Tests/RPC/SignalR/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Tests/RPC/SignalR/appsettings.json b/Tests/RPC/SignalR/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Tests/RPC/SignalR/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Tests/RPC/Thrift/EchoHandler.cs b/Tests/RPC/Thrift/EchoHandler.cs new file mode 100644 index 0000000..94d9df2 --- /dev/null +++ b/Tests/RPC/Thrift/EchoHandler.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Esiur.Tests.RPC.ThriftServer; + +using Echo.ThriftModel; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; + +// using Thrift; // only needed if you reference Thrift exceptions directly + +public sealed class EchoHandler : Echo.ThriftModel.EchoService.IAsync +{ + public Task EchoBytes(byte[] data, CancellationToken cancellationToken = default) + { + return Task.FromResult(data); + } + + public Task> EchoDocuments(List docs, CancellationToken cancellationToken = default) + { + return Task.FromResult(docs); + } + + public Task> EchoIntArray(List array, CancellationToken cancellationToken = default) + { + return Task.FromResult(array); + } + + public Task> EchoStringArray(List array, CancellationToken cancellationToken = default) + { + return Task.FromResult(array); + } + + public Task> EchoMap(Dictionary map, CancellationToken cancellationToken = default) + { + return Task.FromResult(map); + } + + + Task> EchoService.IAsync.EchoEnumArray(List docTypes, CancellationToken cancellationToken) + { + return Task.FromResult(docTypes); + } +} diff --git a/Tests/RPC/Thrift/Esiur.Tests.RPC.ThriftServer.csproj b/Tests/RPC/Thrift/Esiur.Tests.RPC.ThriftServer.csproj new file mode 100644 index 0000000..920b374 --- /dev/null +++ b/Tests/RPC/Thrift/Esiur.Tests.RPC.ThriftServer.csproj @@ -0,0 +1,15 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + + diff --git a/Tests/RPC/Thrift/LoggingHelper.cs b/Tests/RPC/Thrift/LoggingHelper.cs new file mode 100644 index 0000000..83e4c67 --- /dev/null +++ b/Tests/RPC/Thrift/LoggingHelper.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Esiur.Tests.RPC.ThriftServer; +public static class LoggingHelper +{ + public static ILoggerFactory LogFactory { get; } = LoggerFactory.Create(builder => { + ConfigureLogging(builder); + }); + + public static void ConfigureLogging(ILoggingBuilder logging) + { + logging.SetMinimumLevel(LogLevel.Trace); + logging.AddConsole(); + logging.AddDebug(); + } + + public static ILogger CreateLogger() => LogFactory.CreateLogger(); +} \ No newline at end of file diff --git a/Tests/RPC/Thrift/Program.cs b/Tests/RPC/Thrift/Program.cs new file mode 100644 index 0000000..215c7a8 --- /dev/null +++ b/Tests/RPC/Thrift/Program.cs @@ -0,0 +1,16 @@ +using Thrift.Server; +using Thrift.Protocol; +using Thrift.Transport.Server; +using Esiur.Tests.RPC.ThriftServer; + +var handler = new EchoHandler(); +var processor = new Echo.ThriftModel.EchoService.AsyncProcessor(handler); + +var port = 5400; + +var serverTransport = new TServerSocketTransport(port, new Thrift.TConfiguration()); +var server = new TSimpleAsyncServer(processor, serverTransport, new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + LoggingHelper.LogFactory); + +Console.WriteLine($"Thrift server listening on port {port}..."); +await server.ServeAsync(new CancellationToken()); diff --git a/Tests/RPC/Thrift/echo.thrift b/Tests/RPC/Thrift/echo.thrift new file mode 100644 index 0000000..9cd211c --- /dev/null +++ b/Tests/RPC/Thrift/echo.thrift @@ -0,0 +1,179 @@ +namespace netstd Echo.ThriftModel + +// ====================== Enums ====================== + +enum Currency { + IQD = 0, + CNH = 1, + USD = 2, + EUR = 3, + JPY = 4, + GBP = 5 +} + +enum DocType { + Quote = 0, + Order = 1, + Invoice = 2, + CreditNote = 3 +} + +enum PaymentMethod { + Cash = 0, + Card = 1, + Wire = 2, + Crypto = 3, + Other = 4 +} + +enum LineType { + Product = 0, + Service = 1, + Discount = 2, + Shipping = 3 +} + +// Variant.Kind +enum Kind { + Null = 0, + Bool = 1, + Int64 = 2, + UInt64 = 3, + Double = 4, + Decimal = 5, + String = 6, + Bytes = 7, + DateTime = 8, + Guid = 9 +} + +// ====================== Core Value Types ====================== + +// C# Variant: +// Tag: Kind +// Bool: bool? -> optional bool +// I64: long? -> optional i64 +// U64: ulong? -> optional i64 (store unsigned in signed range or with convention) +// F64: double? -> optional double +// Str: string? -> optional string +// Bytes: byte[]? -> optional binary +// Dt: DateTime? -> optional i64 (e.g., Unix epoch millis or ticks) +// Guid: byte[]? -> optional binary +struct Variant { + 1: Kind tag, + 2: optional bool boolVal, + 3: optional i64 i64Val, + 4: optional i64 u64Val, + 5: optional double f64Val, + 6: optional string strVal, + 7: optional binary bytesVal, + 8: optional i64 dtVal, + 9: optional binary guidVal +} + +// Optional helper view of a meta/ext entry (not strictly required, +// since we use map below, but kept to mirror the graph). +struct MetaEntry { + 1: string key, + 2: Variant value +} + +struct ExtEntry { + 1: string key, + 2: Variant value +} + +// ====================== Party & Address ====================== + +struct Address { + 1: string line1, + 2: optional string line2, + 3: string city, + 4: string region, + 5: string country, + 6: optional string postalCode +} + +struct Party { + // C# ulong -> i64 (assumes IDs fit in signed 64-bit) + 1: i64 id, + 2: string name, + 3: optional string taxId, + 4: optional string email, + 5: optional string phone, + 6: optional Address address, + 7: optional string preferredLanguage +} + +// ====================== Document Header ====================== + +// DocId: byte[] +// Type: DocType +// Version: int +// CreatedAt: DateTime -> i64 (e.g. Unix ms) +// UpdatedAt: DateTime? -> optional i64 +// Currency: Currency +// Notes: string? +// Meta: Dictionary -> map +struct DocumentHeader { + 1: binary docId, + 2: DocType type, + 3: i32 version, + 4: i64 createdAt, + 5: optional i64 updatedAt, + 6: Currency currency, + 7: optional string notes, + 8: map meta +} + +// ====================== Line Items, Payments, Attachments ====================== + +struct LineItem { + 1: i32 lineNo, + 2: LineType type, + 3: string sku, + 4: string description, + 5: double qty, + 6: string qtyUnit, + 7: double unitPrice, + 8: optional double vatRate, + 9: optional double discount, + 10: map ext +} + +struct Payment { + 1: PaymentMethod method, + 2: double amount, + 3: optional string reference, + // DateTime -> i64 (e.g. Unix epoch millis or ticks) + 4: i64 timestamp, + 5: optional double fee, + 6: Currency currency +} + +struct Attachment { + 1: string name, + 2: string mimeType, + 3: binary data +} + +// ====================== Top-Level Document ====================== + +struct BusinessDocument { + 1: DocumentHeader header, + 2: Party seller, + 3: Party buyer, + 4: list items, + 5: list payments, + 6: list attachments, + 7: list riskScores +} + +service EchoService { + binary EchoBytes(1: binary data), + list EchoDocuments(1: list docs), + list EchoIntArray(1: list array), + list EchoStringArray(1: list array), + map EchoMap(1: map map), + list EchoEnumArray(1: list docTypes) +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Address.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Address.cs new file mode 100644 index 0000000..e0f313e --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Address.cs @@ -0,0 +1,428 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Address : TBase + { + private string _line1; + private string _line2; + private string _city; + private string _region; + private string _country; + private string _postalCode; + + public string Line1 + { + get + { + return _line1; + } + set + { + __isset.line1 = true; + this._line1 = value; + } + } + + public string Line2 + { + get + { + return _line2; + } + set + { + __isset.line2 = true; + this._line2 = value; + } + } + + public string City + { + get + { + return _city; + } + set + { + __isset.@city = true; + this._city = value; + } + } + + public string Region + { + get + { + return _region; + } + set + { + __isset.@region = true; + this._region = value; + } + } + + public string Country + { + get + { + return _country; + } + set + { + __isset.@country = true; + this._country = value; + } + } + + public string PostalCode + { + get + { + return _postalCode; + } + set + { + __isset.postalCode = true; + this._postalCode = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool line1; + public bool line2; + public bool @city; + public bool @region; + public bool @country; + public bool postalCode; + } + + public Address() + { + } + + public Address DeepCopy() + { + var tmp15 = new Address(); + if((Line1 != null) && __isset.line1) + { + tmp15.Line1 = this.Line1; + } + tmp15.__isset.line1 = this.__isset.line1; + if((Line2 != null) && __isset.line2) + { + tmp15.Line2 = this.Line2; + } + tmp15.__isset.line2 = this.__isset.line2; + if((City != null) && __isset.@city) + { + tmp15.City = this.City; + } + tmp15.__isset.@city = this.__isset.@city; + if((Region != null) && __isset.@region) + { + tmp15.Region = this.Region; + } + tmp15.__isset.@region = this.__isset.@region; + if((Country != null) && __isset.@country) + { + tmp15.Country = this.Country; + } + tmp15.__isset.@country = this.__isset.@country; + if((PostalCode != null) && __isset.postalCode) + { + tmp15.PostalCode = this.PostalCode; + } + tmp15.__isset.postalCode = this.__isset.postalCode; + return tmp15; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Line1 = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + Line2 = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + City = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Region = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.String) + { + Country = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + PostalCode = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp16 = new TStruct("Address"); + await oprot.WriteStructBeginAsync(tmp16, cancellationToken); + var tmp17 = new TField(); + if((Line1 != null) && __isset.line1) + { + tmp17.Name = "line1"; + tmp17.Type = TType.String; + tmp17.ID = 1; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Line1, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Line2 != null) && __isset.line2) + { + tmp17.Name = "line2"; + tmp17.Type = TType.String; + tmp17.ID = 2; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Line2, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((City != null) && __isset.@city) + { + tmp17.Name = "city"; + tmp17.Type = TType.String; + tmp17.ID = 3; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(City, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Region != null) && __isset.@region) + { + tmp17.Name = "region"; + tmp17.Type = TType.String; + tmp17.ID = 4; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Region, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Country != null) && __isset.@country) + { + tmp17.Name = "country"; + tmp17.Type = TType.String; + tmp17.ID = 5; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(Country, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((PostalCode != null) && __isset.postalCode) + { + tmp17.Name = "postalCode"; + tmp17.Type = TType.String; + tmp17.ID = 6; + await oprot.WriteFieldBeginAsync(tmp17, cancellationToken); + await oprot.WriteStringAsync(PostalCode, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Address other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.line1 == other.__isset.line1) && ((!__isset.line1) || (global::System.Object.Equals(Line1, other.Line1)))) + && ((__isset.line2 == other.__isset.line2) && ((!__isset.line2) || (global::System.Object.Equals(Line2, other.Line2)))) + && ((__isset.@city == other.__isset.@city) && ((!__isset.@city) || (global::System.Object.Equals(City, other.City)))) + && ((__isset.@region == other.__isset.@region) && ((!__isset.@region) || (global::System.Object.Equals(Region, other.Region)))) + && ((__isset.@country == other.__isset.@country) && ((!__isset.@country) || (global::System.Object.Equals(Country, other.Country)))) + && ((__isset.postalCode == other.__isset.postalCode) && ((!__isset.postalCode) || (global::System.Object.Equals(PostalCode, other.PostalCode)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Line1 != null) && __isset.line1) + { + hashcode = (hashcode * 397) + Line1.GetHashCode(); + } + if((Line2 != null) && __isset.line2) + { + hashcode = (hashcode * 397) + Line2.GetHashCode(); + } + if((City != null) && __isset.@city) + { + hashcode = (hashcode * 397) + City.GetHashCode(); + } + if((Region != null) && __isset.@region) + { + hashcode = (hashcode * 397) + Region.GetHashCode(); + } + if((Country != null) && __isset.@country) + { + hashcode = (hashcode * 397) + Country.GetHashCode(); + } + if((PostalCode != null) && __isset.postalCode) + { + hashcode = (hashcode * 397) + PostalCode.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp18 = new StringBuilder("Address("); + int tmp19 = 0; + if((Line1 != null) && __isset.line1) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Line1: "); + Line1.ToString(tmp18); + } + if((Line2 != null) && __isset.line2) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Line2: "); + Line2.ToString(tmp18); + } + if((City != null) && __isset.@city) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("City: "); + City.ToString(tmp18); + } + if((Region != null) && __isset.@region) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Region: "); + Region.ToString(tmp18); + } + if((Country != null) && __isset.@country) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("Country: "); + Country.ToString(tmp18); + } + if((PostalCode != null) && __isset.postalCode) + { + if(0 < tmp19++) { tmp18.Append(", "); } + tmp18.Append("PostalCode: "); + PostalCode.ToString(tmp18); + } + tmp18.Append(')'); + return tmp18.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Attachment.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Attachment.cs new file mode 100644 index 0000000..8fb4fa6 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Attachment.cs @@ -0,0 +1,278 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Attachment : TBase + { + private string _name; + private string _mimeType; + private byte[] _data; + + public string Name + { + get + { + return _name; + } + set + { + __isset.@name = true; + this._name = value; + } + } + + public string MimeType + { + get + { + return _mimeType; + } + set + { + __isset.mimeType = true; + this._mimeType = value; + } + } + + public byte[] Data + { + get + { + return _data; + } + set + { + __isset.@data = true; + this._data = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @name; + public bool mimeType; + public bool @data; + } + + public Attachment() + { + } + + public Attachment DeepCopy() + { + var tmp50 = new Attachment(); + if((Name != null) && __isset.@name) + { + tmp50.Name = this.Name; + } + tmp50.__isset.@name = this.__isset.@name; + if((MimeType != null) && __isset.mimeType) + { + tmp50.MimeType = this.MimeType; + } + tmp50.__isset.mimeType = this.__isset.mimeType; + if((Data != null) && __isset.@data) + { + tmp50.Data = this.Data.ToArray(); + } + tmp50.__isset.@data = this.__isset.@data; + return tmp50; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Name = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + MimeType = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Data = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp51 = new TStruct("Attachment"); + await oprot.WriteStructBeginAsync(tmp51, cancellationToken); + var tmp52 = new TField(); + if((Name != null) && __isset.@name) + { + tmp52.Name = "name"; + tmp52.Type = TType.String; + tmp52.ID = 1; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteStringAsync(Name, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((MimeType != null) && __isset.mimeType) + { + tmp52.Name = "mimeType"; + tmp52.Type = TType.String; + tmp52.ID = 2; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteStringAsync(MimeType, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Data != null) && __isset.@data) + { + tmp52.Name = "data"; + tmp52.Type = TType.String; + tmp52.ID = 3; + await oprot.WriteFieldBeginAsync(tmp52, cancellationToken); + await oprot.WriteBinaryAsync(Data, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Attachment other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@name == other.__isset.@name) && ((!__isset.@name) || (global::System.Object.Equals(Name, other.Name)))) + && ((__isset.mimeType == other.__isset.mimeType) && ((!__isset.mimeType) || (global::System.Object.Equals(MimeType, other.MimeType)))) + && ((__isset.@data == other.__isset.@data) && ((!__isset.@data) || (TCollections.Equals(Data, other.Data)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Name != null) && __isset.@name) + { + hashcode = (hashcode * 397) + Name.GetHashCode(); + } + if((MimeType != null) && __isset.mimeType) + { + hashcode = (hashcode * 397) + MimeType.GetHashCode(); + } + if((Data != null) && __isset.@data) + { + hashcode = (hashcode * 397) + Data.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp53 = new StringBuilder("Attachment("); + int tmp54 = 0; + if((Name != null) && __isset.@name) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("Name: "); + Name.ToString(tmp53); + } + if((MimeType != null) && __isset.mimeType) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("MimeType: "); + MimeType.ToString(tmp53); + } + if((Data != null) && __isset.@data) + { + if(0 < tmp54++) { tmp53.Append(", "); } + tmp53.Append("Data: "); + Data.ToString(tmp53); + } + tmp53.Append(')'); + return tmp53.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/BusinessDocument.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/BusinessDocument.cs new file mode 100644 index 0000000..ae3eb18 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/BusinessDocument.cs @@ -0,0 +1,544 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class BusinessDocument : TBase + { + private global::Echo.ThriftModel.DocumentHeader _header; + private global::Echo.ThriftModel.Party _seller; + private global::Echo.ThriftModel.Party _buyer; + private List _items; + private List _payments; + private List _attachments; + private List _riskScores; + + public global::Echo.ThriftModel.DocumentHeader Header + { + get + { + return _header; + } + set + { + __isset.@header = true; + this._header = value; + } + } + + public global::Echo.ThriftModel.Party Seller + { + get + { + return _seller; + } + set + { + __isset.@seller = true; + this._seller = value; + } + } + + public global::Echo.ThriftModel.Party Buyer + { + get + { + return _buyer; + } + set + { + __isset.@buyer = true; + this._buyer = value; + } + } + + public List Items + { + get + { + return _items; + } + set + { + __isset.@items = true; + this._items = value; + } + } + + public List Payments + { + get + { + return _payments; + } + set + { + __isset.@payments = true; + this._payments = value; + } + } + + public List Attachments + { + get + { + return _attachments; + } + set + { + __isset.@attachments = true; + this._attachments = value; + } + } + + public List RiskScores + { + get + { + return _riskScores; + } + set + { + __isset.riskScores = true; + this._riskScores = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @header; + public bool @seller; + public bool @buyer; + public bool @items; + public bool @payments; + public bool @attachments; + public bool riskScores; + } + + public BusinessDocument() + { + } + + public BusinessDocument DeepCopy() + { + var tmp55 = new BusinessDocument(); + if((Header != null) && __isset.@header) + { + tmp55.Header = (global::Echo.ThriftModel.DocumentHeader)this.Header.DeepCopy(); + } + tmp55.__isset.@header = this.__isset.@header; + if((Seller != null) && __isset.@seller) + { + tmp55.Seller = (global::Echo.ThriftModel.Party)this.Seller.DeepCopy(); + } + tmp55.__isset.@seller = this.__isset.@seller; + if((Buyer != null) && __isset.@buyer) + { + tmp55.Buyer = (global::Echo.ThriftModel.Party)this.Buyer.DeepCopy(); + } + tmp55.__isset.@buyer = this.__isset.@buyer; + if((Items != null) && __isset.@items) + { + tmp55.Items = this.Items.DeepCopy(); + } + tmp55.__isset.@items = this.__isset.@items; + if((Payments != null) && __isset.@payments) + { + tmp55.Payments = this.Payments.DeepCopy(); + } + tmp55.__isset.@payments = this.__isset.@payments; + if((Attachments != null) && __isset.@attachments) + { + tmp55.Attachments = this.Attachments.DeepCopy(); + } + tmp55.__isset.@attachments = this.__isset.@attachments; + if((RiskScores != null) && __isset.riskScores) + { + tmp55.RiskScores = this.RiskScores.DeepCopy(); + } + tmp55.__isset.riskScores = this.__isset.riskScores; + return tmp55; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.Struct) + { + Header = new global::Echo.ThriftModel.DocumentHeader(); + await Header.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Seller = new global::Echo.ThriftModel.Party(); + await Seller.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.Struct) + { + Buyer = new global::Echo.ThriftModel.Party(); + await Buyer.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.List) + { + { + var _list56 = await iprot.ReadListBeginAsync(cancellationToken); + Items = new List(_list56.Count); + for(int _i57 = 0; _i57 < _list56.Count; ++_i57) + { + global::Echo.ThriftModel.LineItem _elem58; + _elem58 = new global::Echo.ThriftModel.LineItem(); + await _elem58.ReadAsync(iprot, cancellationToken); + Items.Add(_elem58); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.List) + { + { + var _list59 = await iprot.ReadListBeginAsync(cancellationToken); + Payments = new List(_list59.Count); + for(int _i60 = 0; _i60 < _list59.Count; ++_i60) + { + global::Echo.ThriftModel.Payment _elem61; + _elem61 = new global::Echo.ThriftModel.Payment(); + await _elem61.ReadAsync(iprot, cancellationToken); + Payments.Add(_elem61); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.List) + { + { + var _list62 = await iprot.ReadListBeginAsync(cancellationToken); + Attachments = new List(_list62.Count); + for(int _i63 = 0; _i63 < _list62.Count; ++_i63) + { + global::Echo.ThriftModel.Attachment _elem64; + _elem64 = new global::Echo.ThriftModel.Attachment(); + await _elem64.ReadAsync(iprot, cancellationToken); + Attachments.Add(_elem64); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.List) + { + { + var _list65 = await iprot.ReadListBeginAsync(cancellationToken); + RiskScores = new List(_list65.Count); + for(int _i66 = 0; _i66 < _list65.Count; ++_i66) + { + int _elem67; + _elem67 = await iprot.ReadI32Async(cancellationToken); + RiskScores.Add(_elem67); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp68 = new TStruct("BusinessDocument"); + await oprot.WriteStructBeginAsync(tmp68, cancellationToken); + var tmp69 = new TField(); + if((Header != null) && __isset.@header) + { + tmp69.Name = "header"; + tmp69.Type = TType.Struct; + tmp69.ID = 1; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Header.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Seller != null) && __isset.@seller) + { + tmp69.Name = "seller"; + tmp69.Type = TType.Struct; + tmp69.ID = 2; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Seller.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Buyer != null) && __isset.@buyer) + { + tmp69.Name = "buyer"; + tmp69.Type = TType.Struct; + tmp69.ID = 3; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await Buyer.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Items != null) && __isset.@items) + { + tmp69.Name = "items"; + tmp69.Type = TType.List; + tmp69.ID = 4; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Items.Count), cancellationToken); + foreach (global::Echo.ThriftModel.LineItem _iter70 in Items) + { + await _iter70.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Payments != null) && __isset.@payments) + { + tmp69.Name = "payments"; + tmp69.Type = TType.List; + tmp69.ID = 5; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Payments.Count), cancellationToken); + foreach (global::Echo.ThriftModel.Payment _iter71 in Payments) + { + await _iter71.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Attachments != null) && __isset.@attachments) + { + tmp69.Name = "attachments"; + tmp69.Type = TType.List; + tmp69.ID = 6; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Attachments.Count), cancellationToken); + foreach (global::Echo.ThriftModel.Attachment _iter72 in Attachments) + { + await _iter72.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((RiskScores != null) && __isset.riskScores) + { + tmp69.Name = "riskScores"; + tmp69.Type = TType.List; + tmp69.ID = 7; + await oprot.WriteFieldBeginAsync(tmp69, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, RiskScores.Count), cancellationToken); + foreach (int _iter73 in RiskScores) + { + await oprot.WriteI32Async(_iter73, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is BusinessDocument other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@header == other.__isset.@header) && ((!__isset.@header) || (global::System.Object.Equals(Header, other.Header)))) + && ((__isset.@seller == other.__isset.@seller) && ((!__isset.@seller) || (global::System.Object.Equals(Seller, other.Seller)))) + && ((__isset.@buyer == other.__isset.@buyer) && ((!__isset.@buyer) || (global::System.Object.Equals(Buyer, other.Buyer)))) + && ((__isset.@items == other.__isset.@items) && ((!__isset.@items) || (TCollections.Equals(Items, other.Items)))) + && ((__isset.@payments == other.__isset.@payments) && ((!__isset.@payments) || (TCollections.Equals(Payments, other.Payments)))) + && ((__isset.@attachments == other.__isset.@attachments) && ((!__isset.@attachments) || (TCollections.Equals(Attachments, other.Attachments)))) + && ((__isset.riskScores == other.__isset.riskScores) && ((!__isset.riskScores) || (TCollections.Equals(RiskScores, other.RiskScores)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Header != null) && __isset.@header) + { + hashcode = (hashcode * 397) + Header.GetHashCode(); + } + if((Seller != null) && __isset.@seller) + { + hashcode = (hashcode * 397) + Seller.GetHashCode(); + } + if((Buyer != null) && __isset.@buyer) + { + hashcode = (hashcode * 397) + Buyer.GetHashCode(); + } + if((Items != null) && __isset.@items) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Items); + } + if((Payments != null) && __isset.@payments) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Payments); + } + if((Attachments != null) && __isset.@attachments) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Attachments); + } + if((RiskScores != null) && __isset.riskScores) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(RiskScores); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp74 = new StringBuilder("BusinessDocument("); + int tmp75 = 0; + if((Header != null) && __isset.@header) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Header: "); + Header.ToString(tmp74); + } + if((Seller != null) && __isset.@seller) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Seller: "); + Seller.ToString(tmp74); + } + if((Buyer != null) && __isset.@buyer) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Buyer: "); + Buyer.ToString(tmp74); + } + if((Items != null) && __isset.@items) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Items: "); + Items.ToString(tmp74); + } + if((Payments != null) && __isset.@payments) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Payments: "); + Payments.ToString(tmp74); + } + if((Attachments != null) && __isset.@attachments) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("Attachments: "); + Attachments.ToString(tmp74); + } + if((RiskScores != null) && __isset.riskScores) + { + if(0 < tmp75++) { tmp74.Append(", "); } + tmp74.Append("RiskScores: "); + RiskScores.ToString(tmp74); + } + tmp74.Append(')'); + return tmp74.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Currency.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Currency.cs new file mode 100644 index 0000000..1e84e42 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Currency.cs @@ -0,0 +1,26 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum Currency + { + IQD = 0, + CNH = 1, + USD = 2, + EUR = 3, + JPY = 4, + GBP = 5, + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocType.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocType.cs new file mode 100644 index 0000000..753771b --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocType.cs @@ -0,0 +1,24 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum DocType + { + Quote = 0, + Order = 1, + Invoice = 2, + CreditNote = 3, + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocumentHeader.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocumentHeader.cs new file mode 100644 index 0000000..e578a5d --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/DocumentHeader.cs @@ -0,0 +1,555 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class DocumentHeader : TBase + { + private byte[] _docId; + private global::Echo.ThriftModel.DocType _type; + private int _version; + private long _createdAt; + private long _updatedAt; + private global::Echo.ThriftModel.Currency _currency; + private string _notes; + private Dictionary _meta; + + public byte[] DocId + { + get + { + return _docId; + } + set + { + __isset.docId = true; + this._docId = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.DocType Type + { + get + { + return _type; + } + set + { + __isset.@type = true; + this._type = value; + } + } + + public int Version + { + get + { + return _version; + } + set + { + __isset.@version = true; + this._version = value; + } + } + + public long CreatedAt + { + get + { + return _createdAt; + } + set + { + __isset.createdAt = true; + this._createdAt = value; + } + } + + public long UpdatedAt + { + get + { + return _updatedAt; + } + set + { + __isset.updatedAt = true; + this._updatedAt = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.Currency Currency + { + get + { + return _currency; + } + set + { + __isset.@currency = true; + this._currency = value; + } + } + + public string Notes + { + get + { + return _notes; + } + set + { + __isset.@notes = true; + this._notes = value; + } + } + + public Dictionary Meta + { + get + { + return _meta; + } + set + { + __isset.@meta = true; + this._meta = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool docId; + public bool @type; + public bool @version; + public bool createdAt; + public bool updatedAt; + public bool @currency; + public bool @notes; + public bool @meta; + } + + public DocumentHeader() + { + } + + public DocumentHeader DeepCopy() + { + var tmp25 = new DocumentHeader(); + if((DocId != null) && __isset.docId) + { + tmp25.DocId = this.DocId.ToArray(); + } + tmp25.__isset.docId = this.__isset.docId; + if(__isset.@type) + { + tmp25.Type = this.Type; + } + tmp25.__isset.@type = this.__isset.@type; + if(__isset.@version) + { + tmp25.Version = this.Version; + } + tmp25.__isset.@version = this.__isset.@version; + if(__isset.createdAt) + { + tmp25.CreatedAt = this.CreatedAt; + } + tmp25.__isset.createdAt = this.__isset.createdAt; + if(__isset.updatedAt) + { + tmp25.UpdatedAt = this.UpdatedAt; + } + tmp25.__isset.updatedAt = this.__isset.updatedAt; + if(__isset.@currency) + { + tmp25.Currency = this.Currency; + } + tmp25.__isset.@currency = this.__isset.@currency; + if((Notes != null) && __isset.@notes) + { + tmp25.Notes = this.Notes; + } + tmp25.__isset.@notes = this.__isset.@notes; + if((Meta != null) && __isset.@meta) + { + tmp25.Meta = this.Meta.DeepCopy(); + } + tmp25.__isset.@meta = this.__isset.@meta; + return tmp25; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + DocId = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.I32) + { + Type = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.I32) + { + Version = await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + CreatedAt = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.I64) + { + UpdatedAt = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.I32) + { + Currency = (global::Echo.ThriftModel.Currency)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + Notes = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.Map) + { + { + var _map26 = await iprot.ReadMapBeginAsync(cancellationToken); + Meta = new Dictionary(_map26.Count); + for(int _i27 = 0; _i27 < _map26.Count; ++_i27) + { + string _key28; + global::Echo.ThriftModel.Variant _val29; + _key28 = await iprot.ReadStringAsync(cancellationToken); + _val29 = new global::Echo.ThriftModel.Variant(); + await _val29.ReadAsync(iprot, cancellationToken); + Meta[_key28] = _val29; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp30 = new TStruct("DocumentHeader"); + await oprot.WriteStructBeginAsync(tmp30, cancellationToken); + var tmp31 = new TField(); + if((DocId != null) && __isset.docId) + { + tmp31.Name = "docId"; + tmp31.Type = TType.String; + tmp31.ID = 1; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteBinaryAsync(DocId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@type) + { + tmp31.Name = "type"; + tmp31.Type = TType.I32; + tmp31.ID = 2; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async((int)Type, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@version) + { + tmp31.Name = "version"; + tmp31.Type = TType.I32; + tmp31.ID = 3; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async(Version, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.createdAt) + { + tmp31.Name = "createdAt"; + tmp31.Type = TType.I64; + tmp31.ID = 4; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI64Async(CreatedAt, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.updatedAt) + { + tmp31.Name = "updatedAt"; + tmp31.Type = TType.I64; + tmp31.ID = 5; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI64Async(UpdatedAt, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@currency) + { + tmp31.Name = "currency"; + tmp31.Type = TType.I32; + tmp31.ID = 6; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteI32Async((int)Currency, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Notes != null) && __isset.@notes) + { + tmp31.Name = "notes"; + tmp31.Type = TType.String; + tmp31.ID = 7; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteStringAsync(Notes, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Meta != null) && __isset.@meta) + { + tmp31.Name = "meta"; + tmp31.Type = TType.Map; + tmp31.ID = 8; + await oprot.WriteFieldBeginAsync(tmp31, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Meta.Count), cancellationToken); + foreach (string _iter32 in Meta.Keys) + { + await oprot.WriteStringAsync(_iter32, cancellationToken); + await Meta[_iter32].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is DocumentHeader other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.docId == other.__isset.docId) && ((!__isset.docId) || (TCollections.Equals(DocId, other.DocId)))) + && ((__isset.@type == other.__isset.@type) && ((!__isset.@type) || (global::System.Object.Equals(Type, other.Type)))) + && ((__isset.@version == other.__isset.@version) && ((!__isset.@version) || (global::System.Object.Equals(Version, other.Version)))) + && ((__isset.createdAt == other.__isset.createdAt) && ((!__isset.createdAt) || (global::System.Object.Equals(CreatedAt, other.CreatedAt)))) + && ((__isset.updatedAt == other.__isset.updatedAt) && ((!__isset.updatedAt) || (global::System.Object.Equals(UpdatedAt, other.UpdatedAt)))) + && ((__isset.@currency == other.__isset.@currency) && ((!__isset.@currency) || (global::System.Object.Equals(Currency, other.Currency)))) + && ((__isset.@notes == other.__isset.@notes) && ((!__isset.@notes) || (global::System.Object.Equals(Notes, other.Notes)))) + && ((__isset.@meta == other.__isset.@meta) && ((!__isset.@meta) || (TCollections.Equals(Meta, other.Meta)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((DocId != null) && __isset.docId) + { + hashcode = (hashcode * 397) + DocId.GetHashCode(); + } + if(__isset.@type) + { + hashcode = (hashcode * 397) + Type.GetHashCode(); + } + if(__isset.@version) + { + hashcode = (hashcode * 397) + Version.GetHashCode(); + } + if(__isset.createdAt) + { + hashcode = (hashcode * 397) + CreatedAt.GetHashCode(); + } + if(__isset.updatedAt) + { + hashcode = (hashcode * 397) + UpdatedAt.GetHashCode(); + } + if(__isset.@currency) + { + hashcode = (hashcode * 397) + Currency.GetHashCode(); + } + if((Notes != null) && __isset.@notes) + { + hashcode = (hashcode * 397) + Notes.GetHashCode(); + } + if((Meta != null) && __isset.@meta) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Meta); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp33 = new StringBuilder("DocumentHeader("); + int tmp34 = 0; + if((DocId != null) && __isset.docId) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("DocId: "); + DocId.ToString(tmp33); + } + if(__isset.@type) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Type: "); + Type.ToString(tmp33); + } + if(__isset.@version) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Version: "); + Version.ToString(tmp33); + } + if(__isset.createdAt) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("CreatedAt: "); + CreatedAt.ToString(tmp33); + } + if(__isset.updatedAt) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("UpdatedAt: "); + UpdatedAt.ToString(tmp33); + } + if(__isset.@currency) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Currency: "); + Currency.ToString(tmp33); + } + if((Notes != null) && __isset.@notes) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Notes: "); + Notes.ToString(tmp33); + } + if((Meta != null) && __isset.@meta) + { + if(0 < tmp34++) { tmp33.Append(", "); } + tmp33.Append("Meta: "); + Meta.ToString(tmp33); + } + tmp33.Append(')'); + return tmp33.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/EchoService.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/EchoService.cs new file mode 100644 index 0000000..0a536ee --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/EchoService.cs @@ -0,0 +1,2444 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public partial class EchoService + { + public interface IAsync + { + global::System.Threading.Tasks.Task EchoBytes(byte[] @data, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoDocuments(List @docs, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoIntArray(List @array, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoStringArray(List @array, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoMap(Dictionary @map, CancellationToken cancellationToken = default); + + global::System.Threading.Tasks.Task> EchoEnumArray(List docTypes, CancellationToken cancellationToken = default); + + } + + + public class Client : TBaseClient, IDisposable, IAsync + { + public Client(TProtocol protocol) : this(protocol, protocol) + { + } + + public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol) + { + } + + public async global::System.Threading.Tasks.Task EchoBytes(byte[] @data, CancellationToken cancellationToken = default) + { + await send_EchoBytes(@data, cancellationToken); + return await recv_EchoBytes(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoBytes(byte[] @data, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Call, SeqId), cancellationToken); + + var tmp76 = new InternalStructs.EchoBytes_args() { + Data = @data, + }; + + await tmp76.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task recv_EchoBytes(CancellationToken cancellationToken = default) + { + + var tmp77 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp77.Type == TMessageType.Exception) + { + var tmp78 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp78; + } + + var tmp79 = new InternalStructs.EchoBytes_result(); + await tmp79.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp79.__isset.success) + { + return tmp79.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoBytes failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoDocuments(List @docs, CancellationToken cancellationToken = default) + { + await send_EchoDocuments(@docs, cancellationToken); + return await recv_EchoDocuments(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoDocuments(List @docs, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Call, SeqId), cancellationToken); + + var tmp80 = new InternalStructs.EchoDocuments_args() { + Docs = @docs, + }; + + await tmp80.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoDocuments(CancellationToken cancellationToken = default) + { + + var tmp81 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp81.Type == TMessageType.Exception) + { + var tmp82 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp82; + } + + var tmp83 = new InternalStructs.EchoDocuments_result(); + await tmp83.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp83.__isset.success) + { + return tmp83.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoDocuments failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoIntArray(List @array, CancellationToken cancellationToken = default) + { + await send_EchoIntArray(@array, cancellationToken); + return await recv_EchoIntArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoIntArray(List @array, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp84 = new InternalStructs.EchoIntArray_args() { + Array = @array, + }; + + await tmp84.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoIntArray(CancellationToken cancellationToken = default) + { + + var tmp85 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp85.Type == TMessageType.Exception) + { + var tmp86 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp86; + } + + var tmp87 = new InternalStructs.EchoIntArray_result(); + await tmp87.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp87.__isset.success) + { + return tmp87.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoIntArray failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoStringArray(List @array, CancellationToken cancellationToken = default) + { + await send_EchoStringArray(@array, cancellationToken); + return await recv_EchoStringArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoStringArray(List @array, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp88 = new InternalStructs.EchoStringArray_args() { + Array = @array, + }; + + await tmp88.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoStringArray(CancellationToken cancellationToken = default) + { + + var tmp89 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp89.Type == TMessageType.Exception) + { + var tmp90 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp90; + } + + var tmp91 = new InternalStructs.EchoStringArray_result(); + await tmp91.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp91.__isset.success) + { + return tmp91.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoStringArray failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoMap(Dictionary @map, CancellationToken cancellationToken = default) + { + await send_EchoMap(@map, cancellationToken); + return await recv_EchoMap(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoMap(Dictionary @map, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Call, SeqId), cancellationToken); + + var tmp92 = new InternalStructs.EchoMap_args() { + Map = @map, + }; + + await tmp92.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoMap(CancellationToken cancellationToken = default) + { + + var tmp93 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp93.Type == TMessageType.Exception) + { + var tmp94 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp94; + } + + var tmp95 = new InternalStructs.EchoMap_result(); + await tmp95.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp95.__isset.success) + { + return tmp95.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoMap failed: unknown result"); + } + + public async global::System.Threading.Tasks.Task> EchoEnumArray(List docTypes, CancellationToken cancellationToken = default) + { + await send_EchoEnumArray(docTypes, cancellationToken); + return await recv_EchoEnumArray(cancellationToken); + } + + public async global::System.Threading.Tasks.Task send_EchoEnumArray(List docTypes, CancellationToken cancellationToken = default) + { + await OutputProtocol.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Call, SeqId), cancellationToken); + + var tmp96 = new InternalStructs.EchoEnumArray_args() { + DocTypes = docTypes, + }; + + await tmp96.WriteAsync(OutputProtocol, cancellationToken); + await OutputProtocol.WriteMessageEndAsync(cancellationToken); + await OutputProtocol.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task> recv_EchoEnumArray(CancellationToken cancellationToken = default) + { + + var tmp97 = await InputProtocol.ReadMessageBeginAsync(cancellationToken); + if (tmp97.Type == TMessageType.Exception) + { + var tmp98 = await TApplicationException.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + throw tmp98; + } + + var tmp99 = new InternalStructs.EchoEnumArray_result(); + await tmp99.ReadAsync(InputProtocol, cancellationToken); + await InputProtocol.ReadMessageEndAsync(cancellationToken); + if (tmp99.__isset.success) + { + return tmp99.Success; + } + throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "EchoEnumArray failed: unknown result"); + } + + } + + public class AsyncProcessor : ITAsyncProcessor + { + private readonly IAsync _iAsync; + private readonly ILogger _logger; + + public AsyncProcessor(IAsync iAsync, ILogger logger = default) + { + _iAsync = iAsync ?? throw new ArgumentNullException(nameof(iAsync)); + _logger = logger; + processMap_["EchoBytes"] = EchoBytes_ProcessAsync; + processMap_["EchoDocuments"] = EchoDocuments_ProcessAsync; + processMap_["EchoIntArray"] = EchoIntArray_ProcessAsync; + processMap_["EchoStringArray"] = EchoStringArray_ProcessAsync; + processMap_["EchoMap"] = EchoMap_ProcessAsync; + processMap_["EchoEnumArray"] = EchoEnumArray_ProcessAsync; + } + + protected delegate global::System.Threading.Tasks.Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken); + protected Dictionary processMap_ = new Dictionary(); + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) + { + return await ProcessAsync(iprot, oprot, CancellationToken.None); + } + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + try + { + var msg = await iprot.ReadMessageBeginAsync(cancellationToken); + + processMap_.TryGetValue(msg.Name, out var fn); + + if (fn == null) + { + await TProtocolUtil.SkipAsync(iprot, TType.Struct, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: '" + msg.Name + "'"); + await oprot.WriteMessageBeginAsync(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID), cancellationToken); + await x.WriteAsync(oprot, cancellationToken); + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + return true; + } + + await fn(msg.SeqID, iprot, oprot, cancellationToken); + + } + catch (IOException) + { + return false; + } + + return true; + } + + public async global::System.Threading.Tasks.Task EchoBytes_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp100 = new InternalStructs.EchoBytes_args(); + await tmp100.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp101 = new InternalStructs.EchoBytes_result(); + try + { + tmp101.Success = await _iAsync.EchoBytes(tmp100.Data, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Reply, seqid), cancellationToken); + await tmp101.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp102) + { + var tmp103 = $"Error occurred in {GetType().FullName}: {tmp102.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp102, tmp103); + else + Console.Error.WriteLine(tmp103); + var tmp104 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoBytes", TMessageType.Exception, seqid), cancellationToken); + await tmp104.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoDocuments_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp105 = new InternalStructs.EchoDocuments_args(); + await tmp105.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp106 = new InternalStructs.EchoDocuments_result(); + try + { + tmp106.Success = await _iAsync.EchoDocuments(tmp105.Docs, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Reply, seqid), cancellationToken); + await tmp106.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp107) + { + var tmp108 = $"Error occurred in {GetType().FullName}: {tmp107.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp107, tmp108); + else + Console.Error.WriteLine(tmp108); + var tmp109 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoDocuments", TMessageType.Exception, seqid), cancellationToken); + await tmp109.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoIntArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp110 = new InternalStructs.EchoIntArray_args(); + await tmp110.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp111 = new InternalStructs.EchoIntArray_result(); + try + { + tmp111.Success = await _iAsync.EchoIntArray(tmp110.Array, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Reply, seqid), cancellationToken); + await tmp111.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp112) + { + var tmp113 = $"Error occurred in {GetType().FullName}: {tmp112.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp112, tmp113); + else + Console.Error.WriteLine(tmp113); + var tmp114 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoIntArray", TMessageType.Exception, seqid), cancellationToken); + await tmp114.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoStringArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp115 = new InternalStructs.EchoStringArray_args(); + await tmp115.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp116 = new InternalStructs.EchoStringArray_result(); + try + { + tmp116.Success = await _iAsync.EchoStringArray(tmp115.Array, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Reply, seqid), cancellationToken); + await tmp116.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp117) + { + var tmp118 = $"Error occurred in {GetType().FullName}: {tmp117.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp117, tmp118); + else + Console.Error.WriteLine(tmp118); + var tmp119 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoStringArray", TMessageType.Exception, seqid), cancellationToken); + await tmp119.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoMap_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp120 = new InternalStructs.EchoMap_args(); + await tmp120.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp121 = new InternalStructs.EchoMap_result(); + try + { + tmp121.Success = await _iAsync.EchoMap(tmp120.Map, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Reply, seqid), cancellationToken); + await tmp121.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp122) + { + var tmp123 = $"Error occurred in {GetType().FullName}: {tmp122.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp122, tmp123); + else + Console.Error.WriteLine(tmp123); + var tmp124 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoMap", TMessageType.Exception, seqid), cancellationToken); + await tmp124.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + public async global::System.Threading.Tasks.Task EchoEnumArray_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + var tmp125 = new InternalStructs.EchoEnumArray_args(); + await tmp125.ReadAsync(iprot, cancellationToken); + await iprot.ReadMessageEndAsync(cancellationToken); + var tmp126 = new InternalStructs.EchoEnumArray_result(); + try + { + tmp126.Success = await _iAsync.EchoEnumArray(tmp125.DocTypes, cancellationToken); + await oprot.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Reply, seqid), cancellationToken); + await tmp126.WriteAsync(oprot, cancellationToken); + } + catch (TTransportException) + { + throw; + } + catch (Exception tmp127) + { + var tmp128 = $"Error occurred in {GetType().FullName}: {tmp127.Message}"; + if(_logger != null) + _logger.LogError("{Exception}, {Message}", tmp127, tmp128); + else + Console.Error.WriteLine(tmp128); + var tmp129 = new TApplicationException(TApplicationException.ExceptionType.InternalError," Internal error."); + await oprot.WriteMessageBeginAsync(new TMessage("EchoEnumArray", TMessageType.Exception, seqid), cancellationToken); + await tmp129.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + } + + public class InternalStructs + { + + public partial class EchoBytes_args : TBase + { + private byte[] _data; + + public byte[] Data + { + get + { + return _data; + } + set + { + __isset.@data = true; + this._data = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @data; + } + + public EchoBytes_args() + { + } + + public EchoBytes_args DeepCopy() + { + var tmp130 = new EchoBytes_args(); + if((Data != null) && __isset.@data) + { + tmp130.Data = this.Data.ToArray(); + } + tmp130.__isset.@data = this.__isset.@data; + return tmp130; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Data = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp131 = new TStruct("EchoBytes_args"); + await oprot.WriteStructBeginAsync(tmp131, cancellationToken); + var tmp132 = new TField(); + if((Data != null) && __isset.@data) + { + tmp132.Name = "data"; + tmp132.Type = TType.String; + tmp132.ID = 1; + await oprot.WriteFieldBeginAsync(tmp132, cancellationToken); + await oprot.WriteBinaryAsync(Data, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoBytes_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@data == other.__isset.@data) && ((!__isset.@data) || (TCollections.Equals(Data, other.Data)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Data != null) && __isset.@data) + { + hashcode = (hashcode * 397) + Data.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp133 = new StringBuilder("EchoBytes_args("); + int tmp134 = 0; + if((Data != null) && __isset.@data) + { + if(0 < tmp134++) { tmp133.Append(", "); } + tmp133.Append("Data: "); + Data.ToString(tmp133); + } + tmp133.Append(')'); + return tmp133.ToString(); + } + } + + + public partial class EchoBytes_result : TBase + { + private byte[] _success; + + public byte[] Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoBytes_result() + { + } + + public EchoBytes_result DeepCopy() + { + var tmp135 = new EchoBytes_result(); + if((Success != null) && __isset.@success) + { + tmp135.Success = this.Success.ToArray(); + } + tmp135.__isset.@success = this.__isset.@success; + return tmp135; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.String) + { + Success = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp136 = new TStruct("EchoBytes_result"); + await oprot.WriteStructBeginAsync(tmp136, cancellationToken); + var tmp137 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp137.Name = "Success"; + tmp137.Type = TType.String; + tmp137.ID = 0; + await oprot.WriteFieldBeginAsync(tmp137, cancellationToken); + await oprot.WriteBinaryAsync(Success, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoBytes_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + Success.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp138 = new StringBuilder("EchoBytes_result("); + int tmp139 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp139++) { tmp138.Append(", "); } + tmp138.Append("Success: "); + Success.ToString(tmp138); + } + tmp138.Append(')'); + return tmp138.ToString(); + } + } + + + public partial class EchoDocuments_args : TBase + { + private List _docs; + + public List Docs + { + get + { + return _docs; + } + set + { + __isset.@docs = true; + this._docs = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @docs; + } + + public EchoDocuments_args() + { + } + + public EchoDocuments_args DeepCopy() + { + var tmp140 = new EchoDocuments_args(); + if((Docs != null) && __isset.@docs) + { + tmp140.Docs = this.Docs.DeepCopy(); + } + tmp140.__isset.@docs = this.__isset.@docs; + return tmp140; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list141 = await iprot.ReadListBeginAsync(cancellationToken); + Docs = new List(_list141.Count); + for(int _i142 = 0; _i142 < _list141.Count; ++_i142) + { + global::Echo.ThriftModel.BusinessDocument _elem143; + _elem143 = new global::Echo.ThriftModel.BusinessDocument(); + await _elem143.ReadAsync(iprot, cancellationToken); + Docs.Add(_elem143); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp144 = new TStruct("EchoDocuments_args"); + await oprot.WriteStructBeginAsync(tmp144, cancellationToken); + var tmp145 = new TField(); + if((Docs != null) && __isset.@docs) + { + tmp145.Name = "docs"; + tmp145.Type = TType.List; + tmp145.ID = 1; + await oprot.WriteFieldBeginAsync(tmp145, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Docs.Count), cancellationToken); + foreach (global::Echo.ThriftModel.BusinessDocument _iter146 in Docs) + { + await _iter146.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoDocuments_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@docs == other.__isset.@docs) && ((!__isset.@docs) || (TCollections.Equals(Docs, other.Docs)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Docs != null) && __isset.@docs) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Docs); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp147 = new StringBuilder("EchoDocuments_args("); + int tmp148 = 0; + if((Docs != null) && __isset.@docs) + { + if(0 < tmp148++) { tmp147.Append(", "); } + tmp147.Append("Docs: "); + Docs.ToString(tmp147); + } + tmp147.Append(')'); + return tmp147.ToString(); + } + } + + + public partial class EchoDocuments_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoDocuments_result() + { + } + + public EchoDocuments_result DeepCopy() + { + var tmp149 = new EchoDocuments_result(); + if((Success != null) && __isset.@success) + { + tmp149.Success = this.Success.DeepCopy(); + } + tmp149.__isset.@success = this.__isset.@success; + return tmp149; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list150 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list150.Count); + for(int _i151 = 0; _i151 < _list150.Count; ++_i151) + { + global::Echo.ThriftModel.BusinessDocument _elem152; + _elem152 = new global::Echo.ThriftModel.BusinessDocument(); + await _elem152.ReadAsync(iprot, cancellationToken); + Success.Add(_elem152); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp153 = new TStruct("EchoDocuments_result"); + await oprot.WriteStructBeginAsync(tmp153, cancellationToken); + var tmp154 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp154.Name = "Success"; + tmp154.Type = TType.List; + tmp154.ID = 0; + await oprot.WriteFieldBeginAsync(tmp154, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.Struct, Success.Count), cancellationToken); + foreach (global::Echo.ThriftModel.BusinessDocument _iter155 in Success) + { + await _iter155.WriteAsync(oprot, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoDocuments_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp156 = new StringBuilder("EchoDocuments_result("); + int tmp157 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp157++) { tmp156.Append(", "); } + tmp156.Append("Success: "); + Success.ToString(tmp156); + } + tmp156.Append(')'); + return tmp156.ToString(); + } + } + + + public partial class EchoIntArray_args : TBase + { + private List _array; + + public List Array + { + get + { + return _array; + } + set + { + __isset.@array = true; + this._array = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @array; + } + + public EchoIntArray_args() + { + } + + public EchoIntArray_args DeepCopy() + { + var tmp158 = new EchoIntArray_args(); + if((Array != null) && __isset.@array) + { + tmp158.Array = this.Array.DeepCopy(); + } + tmp158.__isset.@array = this.__isset.@array; + return tmp158; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list159 = await iprot.ReadListBeginAsync(cancellationToken); + Array = new List(_list159.Count); + for(int _i160 = 0; _i160 < _list159.Count; ++_i160) + { + int _elem161; + _elem161 = await iprot.ReadI32Async(cancellationToken); + Array.Add(_elem161); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp162 = new TStruct("EchoIntArray_args"); + await oprot.WriteStructBeginAsync(tmp162, cancellationToken); + var tmp163 = new TField(); + if((Array != null) && __isset.@array) + { + tmp163.Name = "array"; + tmp163.Type = TType.List; + tmp163.ID = 1; + await oprot.WriteFieldBeginAsync(tmp163, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Array.Count), cancellationToken); + foreach (int _iter164 in Array) + { + await oprot.WriteI32Async(_iter164, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoIntArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@array == other.__isset.@array) && ((!__isset.@array) || (TCollections.Equals(Array, other.Array)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Array != null) && __isset.@array) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Array); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp165 = new StringBuilder("EchoIntArray_args("); + int tmp166 = 0; + if((Array != null) && __isset.@array) + { + if(0 < tmp166++) { tmp165.Append(", "); } + tmp165.Append("Array: "); + Array.ToString(tmp165); + } + tmp165.Append(')'); + return tmp165.ToString(); + } + } + + + public partial class EchoIntArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoIntArray_result() + { + } + + public EchoIntArray_result DeepCopy() + { + var tmp167 = new EchoIntArray_result(); + if((Success != null) && __isset.@success) + { + tmp167.Success = this.Success.DeepCopy(); + } + tmp167.__isset.@success = this.__isset.@success; + return tmp167; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list168 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list168.Count); + for(int _i169 = 0; _i169 < _list168.Count; ++_i169) + { + int _elem170; + _elem170 = await iprot.ReadI32Async(cancellationToken); + Success.Add(_elem170); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp171 = new TStruct("EchoIntArray_result"); + await oprot.WriteStructBeginAsync(tmp171, cancellationToken); + var tmp172 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp172.Name = "Success"; + tmp172.Type = TType.List; + tmp172.ID = 0; + await oprot.WriteFieldBeginAsync(tmp172, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Success.Count), cancellationToken); + foreach (int _iter173 in Success) + { + await oprot.WriteI32Async(_iter173, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoIntArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp174 = new StringBuilder("EchoIntArray_result("); + int tmp175 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp175++) { tmp174.Append(", "); } + tmp174.Append("Success: "); + Success.ToString(tmp174); + } + tmp174.Append(')'); + return tmp174.ToString(); + } + } + + + public partial class EchoStringArray_args : TBase + { + private List _array; + + public List Array + { + get + { + return _array; + } + set + { + __isset.@array = true; + this._array = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @array; + } + + public EchoStringArray_args() + { + } + + public EchoStringArray_args DeepCopy() + { + var tmp176 = new EchoStringArray_args(); + if((Array != null) && __isset.@array) + { + tmp176.Array = this.Array.DeepCopy(); + } + tmp176.__isset.@array = this.__isset.@array; + return tmp176; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list177 = await iprot.ReadListBeginAsync(cancellationToken); + Array = new List(_list177.Count); + for(int _i178 = 0; _i178 < _list177.Count; ++_i178) + { + string _elem179; + _elem179 = await iprot.ReadStringAsync(cancellationToken); + Array.Add(_elem179); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp180 = new TStruct("EchoStringArray_args"); + await oprot.WriteStructBeginAsync(tmp180, cancellationToken); + var tmp181 = new TField(); + if((Array != null) && __isset.@array) + { + tmp181.Name = "array"; + tmp181.Type = TType.List; + tmp181.ID = 1; + await oprot.WriteFieldBeginAsync(tmp181, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.String, Array.Count), cancellationToken); + foreach (string _iter182 in Array) + { + await oprot.WriteStringAsync(_iter182, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoStringArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@array == other.__isset.@array) && ((!__isset.@array) || (TCollections.Equals(Array, other.Array)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Array != null) && __isset.@array) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Array); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp183 = new StringBuilder("EchoStringArray_args("); + int tmp184 = 0; + if((Array != null) && __isset.@array) + { + if(0 < tmp184++) { tmp183.Append(", "); } + tmp183.Append("Array: "); + Array.ToString(tmp183); + } + tmp183.Append(')'); + return tmp183.ToString(); + } + } + + + public partial class EchoStringArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoStringArray_result() + { + } + + public EchoStringArray_result DeepCopy() + { + var tmp185 = new EchoStringArray_result(); + if((Success != null) && __isset.@success) + { + tmp185.Success = this.Success.DeepCopy(); + } + tmp185.__isset.@success = this.__isset.@success; + return tmp185; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list186 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list186.Count); + for(int _i187 = 0; _i187 < _list186.Count; ++_i187) + { + string _elem188; + _elem188 = await iprot.ReadStringAsync(cancellationToken); + Success.Add(_elem188); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp189 = new TStruct("EchoStringArray_result"); + await oprot.WriteStructBeginAsync(tmp189, cancellationToken); + var tmp190 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp190.Name = "Success"; + tmp190.Type = TType.List; + tmp190.ID = 0; + await oprot.WriteFieldBeginAsync(tmp190, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.String, Success.Count), cancellationToken); + foreach (string _iter191 in Success) + { + await oprot.WriteStringAsync(_iter191, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoStringArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp192 = new StringBuilder("EchoStringArray_result("); + int tmp193 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp193++) { tmp192.Append(", "); } + tmp192.Append("Success: "); + Success.ToString(tmp192); + } + tmp192.Append(')'); + return tmp192.ToString(); + } + } + + + public partial class EchoMap_args : TBase + { + private Dictionary _map; + + public Dictionary Map + { + get + { + return _map; + } + set + { + __isset.@map = true; + this._map = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @map; + } + + public EchoMap_args() + { + } + + public EchoMap_args DeepCopy() + { + var tmp194 = new EchoMap_args(); + if((Map != null) && __isset.@map) + { + tmp194.Map = this.Map.DeepCopy(); + } + tmp194.__isset.@map = this.__isset.@map; + return tmp194; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.Map) + { + { + var _map195 = await iprot.ReadMapBeginAsync(cancellationToken); + Map = new Dictionary(_map195.Count); + for(int _i196 = 0; _i196 < _map195.Count; ++_i196) + { + string _key197; + global::Echo.ThriftModel.BusinessDocument _val198; + _key197 = await iprot.ReadStringAsync(cancellationToken); + _val198 = new global::Echo.ThriftModel.BusinessDocument(); + await _val198.ReadAsync(iprot, cancellationToken); + Map[_key197] = _val198; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp199 = new TStruct("EchoMap_args"); + await oprot.WriteStructBeginAsync(tmp199, cancellationToken); + var tmp200 = new TField(); + if((Map != null) && __isset.@map) + { + tmp200.Name = "map"; + tmp200.Type = TType.Map; + tmp200.ID = 1; + await oprot.WriteFieldBeginAsync(tmp200, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Map.Count), cancellationToken); + foreach (string _iter201 in Map.Keys) + { + await oprot.WriteStringAsync(_iter201, cancellationToken); + await Map[_iter201].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoMap_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@map == other.__isset.@map) && ((!__isset.@map) || (TCollections.Equals(Map, other.Map)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Map != null) && __isset.@map) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Map); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp202 = new StringBuilder("EchoMap_args("); + int tmp203 = 0; + if((Map != null) && __isset.@map) + { + if(0 < tmp203++) { tmp202.Append(", "); } + tmp202.Append("Map: "); + Map.ToString(tmp202); + } + tmp202.Append(')'); + return tmp202.ToString(); + } + } + + + public partial class EchoMap_result : TBase + { + private Dictionary _success; + + public Dictionary Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoMap_result() + { + } + + public EchoMap_result DeepCopy() + { + var tmp204 = new EchoMap_result(); + if((Success != null) && __isset.@success) + { + tmp204.Success = this.Success.DeepCopy(); + } + tmp204.__isset.@success = this.__isset.@success; + return tmp204; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.Map) + { + { + var _map205 = await iprot.ReadMapBeginAsync(cancellationToken); + Success = new Dictionary(_map205.Count); + for(int _i206 = 0; _i206 < _map205.Count; ++_i206) + { + string _key207; + global::Echo.ThriftModel.BusinessDocument _val208; + _key207 = await iprot.ReadStringAsync(cancellationToken); + _val208 = new global::Echo.ThriftModel.BusinessDocument(); + await _val208.ReadAsync(iprot, cancellationToken); + Success[_key207] = _val208; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp209 = new TStruct("EchoMap_result"); + await oprot.WriteStructBeginAsync(tmp209, cancellationToken); + var tmp210 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp210.Name = "Success"; + tmp210.Type = TType.Map; + tmp210.ID = 0; + await oprot.WriteFieldBeginAsync(tmp210, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Success.Count), cancellationToken); + foreach (string _iter211 in Success.Keys) + { + await oprot.WriteStringAsync(_iter211, cancellationToken); + await Success[_iter211].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoMap_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp212 = new StringBuilder("EchoMap_result("); + int tmp213 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp213++) { tmp212.Append(", "); } + tmp212.Append("Success: "); + Success.ToString(tmp212); + } + tmp212.Append(')'); + return tmp212.ToString(); + } + } + + + public partial class EchoEnumArray_args : TBase + { + private List _docTypes; + + public List DocTypes + { + get + { + return _docTypes; + } + set + { + __isset.docTypes = true; + this._docTypes = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool docTypes; + } + + public EchoEnumArray_args() + { + } + + public EchoEnumArray_args DeepCopy() + { + var tmp214 = new EchoEnumArray_args(); + if((DocTypes != null) && __isset.docTypes) + { + tmp214.DocTypes = this.DocTypes.DeepCopy(); + } + tmp214.__isset.docTypes = this.__isset.docTypes; + return tmp214; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.List) + { + { + var _list215 = await iprot.ReadListBeginAsync(cancellationToken); + DocTypes = new List(_list215.Count); + for(int _i216 = 0; _i216 < _list215.Count; ++_i216) + { + global::Echo.ThriftModel.DocType _elem217; + _elem217 = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + DocTypes.Add(_elem217); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp218 = new TStruct("EchoEnumArray_args"); + await oprot.WriteStructBeginAsync(tmp218, cancellationToken); + var tmp219 = new TField(); + if((DocTypes != null) && __isset.docTypes) + { + tmp219.Name = "docTypes"; + tmp219.Type = TType.List; + tmp219.ID = 1; + await oprot.WriteFieldBeginAsync(tmp219, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, DocTypes.Count), cancellationToken); + foreach (global::Echo.ThriftModel.DocType _iter220 in DocTypes) + { + await oprot.WriteI32Async((int)_iter220, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoEnumArray_args other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.docTypes == other.__isset.docTypes) && ((!__isset.docTypes) || (TCollections.Equals(DocTypes, other.DocTypes)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((DocTypes != null) && __isset.docTypes) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(DocTypes); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp221 = new StringBuilder("EchoEnumArray_args("); + int tmp222 = 0; + if((DocTypes != null) && __isset.docTypes) + { + if(0 < tmp222++) { tmp221.Append(", "); } + tmp221.Append("DocTypes: "); + DocTypes.ToString(tmp221); + } + tmp221.Append(')'); + return tmp221.ToString(); + } + } + + + public partial class EchoEnumArray_result : TBase + { + private List _success; + + public List Success + { + get + { + return _success; + } + set + { + __isset.@success = true; + this._success = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @success; + } + + public EchoEnumArray_result() + { + } + + public EchoEnumArray_result DeepCopy() + { + var tmp223 = new EchoEnumArray_result(); + if((Success != null) && __isset.@success) + { + tmp223.Success = this.Success.DeepCopy(); + } + tmp223.__isset.@success = this.__isset.@success; + return tmp223; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 0: + if (field.Type == TType.List) + { + { + var _list224 = await iprot.ReadListBeginAsync(cancellationToken); + Success = new List(_list224.Count); + for(int _i225 = 0; _i225 < _list224.Count; ++_i225) + { + global::Echo.ThriftModel.DocType _elem226; + _elem226 = (global::Echo.ThriftModel.DocType)await iprot.ReadI32Async(cancellationToken); + Success.Add(_elem226); + } + await iprot.ReadListEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp227 = new TStruct("EchoEnumArray_result"); + await oprot.WriteStructBeginAsync(tmp227, cancellationToken); + var tmp228 = new TField(); + + if(this.__isset.@success) + { + if (Success != null) + { + tmp228.Name = "Success"; + tmp228.Type = TType.List; + tmp228.ID = 0; + await oprot.WriteFieldBeginAsync(tmp228, cancellationToken); + await oprot.WriteListBeginAsync(new TList(TType.I32, Success.Count), cancellationToken); + foreach (global::Echo.ThriftModel.DocType _iter229 in Success) + { + await oprot.WriteI32Async((int)_iter229, cancellationToken); + } + await oprot.WriteListEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is EchoEnumArray_result other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@success == other.__isset.@success) && ((!__isset.@success) || (TCollections.Equals(Success, other.Success)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Success != null) && __isset.@success) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Success); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp230 = new StringBuilder("EchoEnumArray_result("); + int tmp231 = 0; + if((Success != null) && __isset.@success) + { + if(0 < tmp231++) { tmp230.Append(", "); } + tmp230.Append("Success: "); + Success.ToString(tmp230); + } + tmp230.Append(')'); + return tmp230.ToString(); + } + } + + } + + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/ExtEntry.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/ExtEntry.cs new file mode 100644 index 0000000..3922f80 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/ExtEntry.cs @@ -0,0 +1,229 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class ExtEntry : TBase + { + private string _key; + private global::Echo.ThriftModel.Variant _value; + + public string Key + { + get + { + return _key; + } + set + { + __isset.@key = true; + this._key = value; + } + } + + public global::Echo.ThriftModel.Variant Value + { + get + { + return _value; + } + set + { + __isset.@value = true; + this._value = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @key; + public bool @value; + } + + public ExtEntry() + { + } + + public ExtEntry DeepCopy() + { + var tmp10 = new ExtEntry(); + if((Key != null) && __isset.@key) + { + tmp10.Key = this.Key; + } + tmp10.__isset.@key = this.__isset.@key; + if((Value != null) && __isset.@value) + { + tmp10.Value = (global::Echo.ThriftModel.Variant)this.Value.DeepCopy(); + } + tmp10.__isset.@value = this.__isset.@value; + return tmp10; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Key = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Value = new global::Echo.ThriftModel.Variant(); + await Value.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp11 = new TStruct("ExtEntry"); + await oprot.WriteStructBeginAsync(tmp11, cancellationToken); + var tmp12 = new TField(); + if((Key != null) && __isset.@key) + { + tmp12.Name = "key"; + tmp12.Type = TType.String; + tmp12.ID = 1; + await oprot.WriteFieldBeginAsync(tmp12, cancellationToken); + await oprot.WriteStringAsync(Key, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Value != null) && __isset.@value) + { + tmp12.Name = "value"; + tmp12.Type = TType.Struct; + tmp12.ID = 2; + await oprot.WriteFieldBeginAsync(tmp12, cancellationToken); + await Value.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is ExtEntry other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@key == other.__isset.@key) && ((!__isset.@key) || (global::System.Object.Equals(Key, other.Key)))) + && ((__isset.@value == other.__isset.@value) && ((!__isset.@value) || (global::System.Object.Equals(Value, other.Value)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Key != null) && __isset.@key) + { + hashcode = (hashcode * 397) + Key.GetHashCode(); + } + if((Value != null) && __isset.@value) + { + hashcode = (hashcode * 397) + Value.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp13 = new StringBuilder("ExtEntry("); + int tmp14 = 0; + if((Key != null) && __isset.@key) + { + if(0 < tmp14++) { tmp13.Append(", "); } + tmp13.Append("Key: "); + Key.ToString(tmp13); + } + if((Value != null) && __isset.@value) + { + if(0 < tmp14++) { tmp13.Append(", "); } + tmp13.Append("Value: "); + Value.ToString(tmp13); + } + tmp13.Append(')'); + return tmp13.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Kind.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Kind.cs new file mode 100644 index 0000000..34f7bed --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Kind.cs @@ -0,0 +1,30 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum Kind + { + @Null = 0, + @Bool = 1, + Int64 = 2, + UInt64 = 3, + @Double = 4, + @Decimal = 5, + @String = 6, + Bytes = 7, + DateTime = 8, + Guid = 9, + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineItem.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineItem.cs new file mode 100644 index 0000000..13030bc --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineItem.cs @@ -0,0 +1,651 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class LineItem : TBase + { + private int _lineNo; + private global::Echo.ThriftModel.LineType _type; + private string _sku; + private string _description; + private double _qty; + private string _qtyUnit; + private double _unitPrice; + private double _vatRate; + private double _discount; + private Dictionary _ext; + + public int LineNo + { + get + { + return _lineNo; + } + set + { + __isset.lineNo = true; + this._lineNo = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.LineType Type + { + get + { + return _type; + } + set + { + __isset.@type = true; + this._type = value; + } + } + + public string Sku + { + get + { + return _sku; + } + set + { + __isset.@sku = true; + this._sku = value; + } + } + + public string Description + { + get + { + return _description; + } + set + { + __isset.@description = true; + this._description = value; + } + } + + public double Qty + { + get + { + return _qty; + } + set + { + __isset.@qty = true; + this._qty = value; + } + } + + public string QtyUnit + { + get + { + return _qtyUnit; + } + set + { + __isset.qtyUnit = true; + this._qtyUnit = value; + } + } + + public double UnitPrice + { + get + { + return _unitPrice; + } + set + { + __isset.unitPrice = true; + this._unitPrice = value; + } + } + + public double VatRate + { + get + { + return _vatRate; + } + set + { + __isset.vatRate = true; + this._vatRate = value; + } + } + + public double Discount + { + get + { + return _discount; + } + set + { + __isset.@discount = true; + this._discount = value; + } + } + + public Dictionary Ext + { + get + { + return _ext; + } + set + { + __isset.@ext = true; + this._ext = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool lineNo; + public bool @type; + public bool @sku; + public bool @description; + public bool @qty; + public bool qtyUnit; + public bool unitPrice; + public bool vatRate; + public bool @discount; + public bool @ext; + } + + public LineItem() + { + } + + public LineItem DeepCopy() + { + var tmp35 = new LineItem(); + if(__isset.lineNo) + { + tmp35.LineNo = this.LineNo; + } + tmp35.__isset.lineNo = this.__isset.lineNo; + if(__isset.@type) + { + tmp35.Type = this.Type; + } + tmp35.__isset.@type = this.__isset.@type; + if((Sku != null) && __isset.@sku) + { + tmp35.Sku = this.Sku; + } + tmp35.__isset.@sku = this.__isset.@sku; + if((Description != null) && __isset.@description) + { + tmp35.Description = this.Description; + } + tmp35.__isset.@description = this.__isset.@description; + if(__isset.@qty) + { + tmp35.Qty = this.Qty; + } + tmp35.__isset.@qty = this.__isset.@qty; + if((QtyUnit != null) && __isset.qtyUnit) + { + tmp35.QtyUnit = this.QtyUnit; + } + tmp35.__isset.qtyUnit = this.__isset.qtyUnit; + if(__isset.unitPrice) + { + tmp35.UnitPrice = this.UnitPrice; + } + tmp35.__isset.unitPrice = this.__isset.unitPrice; + if(__isset.vatRate) + { + tmp35.VatRate = this.VatRate; + } + tmp35.__isset.vatRate = this.__isset.vatRate; + if(__isset.@discount) + { + tmp35.Discount = this.Discount; + } + tmp35.__isset.@discount = this.__isset.@discount; + if((Ext != null) && __isset.@ext) + { + tmp35.Ext = this.Ext.DeepCopy(); + } + tmp35.__isset.@ext = this.__isset.@ext; + return tmp35; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + LineNo = await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.I32) + { + Type = (global::Echo.ThriftModel.LineType)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Sku = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Description = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + Qty = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + QtyUnit = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.Double) + { + UnitPrice = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.Double) + { + VatRate = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 9: + if (field.Type == TType.Double) + { + Discount = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 10: + if (field.Type == TType.Map) + { + { + var _map36 = await iprot.ReadMapBeginAsync(cancellationToken); + Ext = new Dictionary(_map36.Count); + for(int _i37 = 0; _i37 < _map36.Count; ++_i37) + { + string _key38; + global::Echo.ThriftModel.Variant _val39; + _key38 = await iprot.ReadStringAsync(cancellationToken); + _val39 = new global::Echo.ThriftModel.Variant(); + await _val39.ReadAsync(iprot, cancellationToken); + Ext[_key38] = _val39; + } + await iprot.ReadMapEndAsync(cancellationToken); + } + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp40 = new TStruct("LineItem"); + await oprot.WriteStructBeginAsync(tmp40, cancellationToken); + var tmp41 = new TField(); + if(__isset.lineNo) + { + tmp41.Name = "lineNo"; + tmp41.Type = TType.I32; + tmp41.ID = 1; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteI32Async(LineNo, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@type) + { + tmp41.Name = "type"; + tmp41.Type = TType.I32; + tmp41.ID = 2; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteI32Async((int)Type, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Sku != null) && __isset.@sku) + { + tmp41.Name = "sku"; + tmp41.Type = TType.String; + tmp41.ID = 3; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(Sku, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Description != null) && __isset.@description) + { + tmp41.Name = "description"; + tmp41.Type = TType.String; + tmp41.ID = 4; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(Description, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@qty) + { + tmp41.Name = "qty"; + tmp41.Type = TType.Double; + tmp41.ID = 5; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(Qty, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + tmp41.Name = "qtyUnit"; + tmp41.Type = TType.String; + tmp41.ID = 6; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteStringAsync(QtyUnit, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.unitPrice) + { + tmp41.Name = "unitPrice"; + tmp41.Type = TType.Double; + tmp41.ID = 7; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(UnitPrice, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.vatRate) + { + tmp41.Name = "vatRate"; + tmp41.Type = TType.Double; + tmp41.ID = 8; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(VatRate, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@discount) + { + tmp41.Name = "discount"; + tmp41.Type = TType.Double; + tmp41.ID = 9; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteDoubleAsync(Discount, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Ext != null) && __isset.@ext) + { + tmp41.Name = "ext"; + tmp41.Type = TType.Map; + tmp41.ID = 10; + await oprot.WriteFieldBeginAsync(tmp41, cancellationToken); + await oprot.WriteMapBeginAsync(new TMap(TType.String, TType.Struct, Ext.Count), cancellationToken); + foreach (string _iter42 in Ext.Keys) + { + await oprot.WriteStringAsync(_iter42, cancellationToken); + await Ext[_iter42].WriteAsync(oprot, cancellationToken); + } + await oprot.WriteMapEndAsync(cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is LineItem other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.lineNo == other.__isset.lineNo) && ((!__isset.lineNo) || (global::System.Object.Equals(LineNo, other.LineNo)))) + && ((__isset.@type == other.__isset.@type) && ((!__isset.@type) || (global::System.Object.Equals(Type, other.Type)))) + && ((__isset.@sku == other.__isset.@sku) && ((!__isset.@sku) || (global::System.Object.Equals(Sku, other.Sku)))) + && ((__isset.@description == other.__isset.@description) && ((!__isset.@description) || (global::System.Object.Equals(Description, other.Description)))) + && ((__isset.@qty == other.__isset.@qty) && ((!__isset.@qty) || (global::System.Object.Equals(Qty, other.Qty)))) + && ((__isset.qtyUnit == other.__isset.qtyUnit) && ((!__isset.qtyUnit) || (global::System.Object.Equals(QtyUnit, other.QtyUnit)))) + && ((__isset.unitPrice == other.__isset.unitPrice) && ((!__isset.unitPrice) || (global::System.Object.Equals(UnitPrice, other.UnitPrice)))) + && ((__isset.vatRate == other.__isset.vatRate) && ((!__isset.vatRate) || (global::System.Object.Equals(VatRate, other.VatRate)))) + && ((__isset.@discount == other.__isset.@discount) && ((!__isset.@discount) || (global::System.Object.Equals(Discount, other.Discount)))) + && ((__isset.@ext == other.__isset.@ext) && ((!__isset.@ext) || (TCollections.Equals(Ext, other.Ext)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.lineNo) + { + hashcode = (hashcode * 397) + LineNo.GetHashCode(); + } + if(__isset.@type) + { + hashcode = (hashcode * 397) + Type.GetHashCode(); + } + if((Sku != null) && __isset.@sku) + { + hashcode = (hashcode * 397) + Sku.GetHashCode(); + } + if((Description != null) && __isset.@description) + { + hashcode = (hashcode * 397) + Description.GetHashCode(); + } + if(__isset.@qty) + { + hashcode = (hashcode * 397) + Qty.GetHashCode(); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + hashcode = (hashcode * 397) + QtyUnit.GetHashCode(); + } + if(__isset.unitPrice) + { + hashcode = (hashcode * 397) + UnitPrice.GetHashCode(); + } + if(__isset.vatRate) + { + hashcode = (hashcode * 397) + VatRate.GetHashCode(); + } + if(__isset.@discount) + { + hashcode = (hashcode * 397) + Discount.GetHashCode(); + } + if((Ext != null) && __isset.@ext) + { + hashcode = (hashcode * 397) + TCollections.GetHashCode(Ext); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp43 = new StringBuilder("LineItem("); + int tmp44 = 0; + if(__isset.lineNo) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("LineNo: "); + LineNo.ToString(tmp43); + } + if(__isset.@type) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Type: "); + Type.ToString(tmp43); + } + if((Sku != null) && __isset.@sku) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Sku: "); + Sku.ToString(tmp43); + } + if((Description != null) && __isset.@description) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Description: "); + Description.ToString(tmp43); + } + if(__isset.@qty) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Qty: "); + Qty.ToString(tmp43); + } + if((QtyUnit != null) && __isset.qtyUnit) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("QtyUnit: "); + QtyUnit.ToString(tmp43); + } + if(__isset.unitPrice) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("UnitPrice: "); + UnitPrice.ToString(tmp43); + } + if(__isset.vatRate) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("VatRate: "); + VatRate.ToString(tmp43); + } + if(__isset.@discount) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Discount: "); + Discount.ToString(tmp43); + } + if((Ext != null) && __isset.@ext) + { + if(0 < tmp44++) { tmp43.Append(", "); } + tmp43.Append("Ext: "); + Ext.ToString(tmp43); + } + tmp43.Append(')'); + return tmp43.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineType.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineType.cs new file mode 100644 index 0000000..83fe925 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/LineType.cs @@ -0,0 +1,24 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum LineType + { + Product = 0, + Service = 1, + Discount = 2, + Shipping = 3, + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/MetaEntry.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/MetaEntry.cs new file mode 100644 index 0000000..7cc77a0 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/MetaEntry.cs @@ -0,0 +1,229 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class MetaEntry : TBase + { + private string _key; + private global::Echo.ThriftModel.Variant _value; + + public string Key + { + get + { + return _key; + } + set + { + __isset.@key = true; + this._key = value; + } + } + + public global::Echo.ThriftModel.Variant Value + { + get + { + return _value; + } + set + { + __isset.@value = true; + this._value = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @key; + public bool @value; + } + + public MetaEntry() + { + } + + public MetaEntry DeepCopy() + { + var tmp5 = new MetaEntry(); + if((Key != null) && __isset.@key) + { + tmp5.Key = this.Key; + } + tmp5.__isset.@key = this.__isset.@key; + if((Value != null) && __isset.@value) + { + tmp5.Value = (global::Echo.ThriftModel.Variant)this.Value.DeepCopy(); + } + tmp5.__isset.@value = this.__isset.@value; + return tmp5; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + Key = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Struct) + { + Value = new global::Echo.ThriftModel.Variant(); + await Value.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp6 = new TStruct("MetaEntry"); + await oprot.WriteStructBeginAsync(tmp6, cancellationToken); + var tmp7 = new TField(); + if((Key != null) && __isset.@key) + { + tmp7.Name = "key"; + tmp7.Type = TType.String; + tmp7.ID = 1; + await oprot.WriteFieldBeginAsync(tmp7, cancellationToken); + await oprot.WriteStringAsync(Key, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Value != null) && __isset.@value) + { + tmp7.Name = "value"; + tmp7.Type = TType.Struct; + tmp7.ID = 2; + await oprot.WriteFieldBeginAsync(tmp7, cancellationToken); + await Value.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is MetaEntry other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@key == other.__isset.@key) && ((!__isset.@key) || (global::System.Object.Equals(Key, other.Key)))) + && ((__isset.@value == other.__isset.@value) && ((!__isset.@value) || (global::System.Object.Equals(Value, other.Value)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if((Key != null) && __isset.@key) + { + hashcode = (hashcode * 397) + Key.GetHashCode(); + } + if((Value != null) && __isset.@value) + { + hashcode = (hashcode * 397) + Value.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp8 = new StringBuilder("MetaEntry("); + int tmp9 = 0; + if((Key != null) && __isset.@key) + { + if(0 < tmp9++) { tmp8.Append(", "); } + tmp8.Append("Key: "); + Key.ToString(tmp8); + } + if((Value != null) && __isset.@value) + { + if(0 < tmp9++) { tmp8.Append(", "); } + tmp8.Append("Value: "); + Value.ToString(tmp8); + } + tmp8.Append(')'); + return tmp8.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Party.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Party.cs new file mode 100644 index 0000000..42bb371 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Party.cs @@ -0,0 +1,479 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Party : TBase + { + private long _id; + private string _name; + private string _taxId; + private string _email; + private string _phone; + private global::Echo.ThriftModel.Address _address; + private string _preferredLanguage; + + public long Id + { + get + { + return _id; + } + set + { + __isset.@id = true; + this._id = value; + } + } + + public string Name + { + get + { + return _name; + } + set + { + __isset.@name = true; + this._name = value; + } + } + + public string TaxId + { + get + { + return _taxId; + } + set + { + __isset.taxId = true; + this._taxId = value; + } + } + + public string Email + { + get + { + return _email; + } + set + { + __isset.@email = true; + this._email = value; + } + } + + public string Phone + { + get + { + return _phone; + } + set + { + __isset.@phone = true; + this._phone = value; + } + } + + public global::Echo.ThriftModel.Address Address + { + get + { + return _address; + } + set + { + __isset.@address = true; + this._address = value; + } + } + + public string PreferredLanguage + { + get + { + return _preferredLanguage; + } + set + { + __isset.preferredLanguage = true; + this._preferredLanguage = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @id; + public bool @name; + public bool taxId; + public bool @email; + public bool @phone; + public bool @address; + public bool preferredLanguage; + } + + public Party() + { + } + + public Party DeepCopy() + { + var tmp20 = new Party(); + if(__isset.@id) + { + tmp20.Id = this.Id; + } + tmp20.__isset.@id = this.__isset.@id; + if((Name != null) && __isset.@name) + { + tmp20.Name = this.Name; + } + tmp20.__isset.@name = this.__isset.@name; + if((TaxId != null) && __isset.taxId) + { + tmp20.TaxId = this.TaxId; + } + tmp20.__isset.taxId = this.__isset.taxId; + if((Email != null) && __isset.@email) + { + tmp20.Email = this.Email; + } + tmp20.__isset.@email = this.__isset.@email; + if((Phone != null) && __isset.@phone) + { + tmp20.Phone = this.Phone; + } + tmp20.__isset.@phone = this.__isset.@phone; + if((Address != null) && __isset.@address) + { + tmp20.Address = (global::Echo.ThriftModel.Address)this.Address.DeepCopy(); + } + tmp20.__isset.@address = this.__isset.@address; + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + tmp20.PreferredLanguage = this.PreferredLanguage; + } + tmp20.__isset.preferredLanguage = this.__isset.preferredLanguage; + return tmp20; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I64) + { + Id = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.String) + { + Name = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + TaxId = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.String) + { + Email = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.String) + { + Phone = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.Struct) + { + Address = new global::Echo.ThriftModel.Address(); + await Address.ReadAsync(iprot, cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + PreferredLanguage = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp21 = new TStruct("Party"); + await oprot.WriteStructBeginAsync(tmp21, cancellationToken); + var tmp22 = new TField(); + if(__isset.@id) + { + tmp22.Name = "id"; + tmp22.Type = TType.I64; + tmp22.ID = 1; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteI64Async(Id, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Name != null) && __isset.@name) + { + tmp22.Name = "name"; + tmp22.Type = TType.String; + tmp22.ID = 2; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Name, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((TaxId != null) && __isset.taxId) + { + tmp22.Name = "taxId"; + tmp22.Type = TType.String; + tmp22.ID = 3; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(TaxId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Email != null) && __isset.@email) + { + tmp22.Name = "email"; + tmp22.Type = TType.String; + tmp22.ID = 4; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Email, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Phone != null) && __isset.@phone) + { + tmp22.Name = "phone"; + tmp22.Type = TType.String; + tmp22.ID = 5; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(Phone, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Address != null) && __isset.@address) + { + tmp22.Name = "address"; + tmp22.Type = TType.Struct; + tmp22.ID = 6; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await Address.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + tmp22.Name = "preferredLanguage"; + tmp22.Type = TType.String; + tmp22.ID = 7; + await oprot.WriteFieldBeginAsync(tmp22, cancellationToken); + await oprot.WriteStringAsync(PreferredLanguage, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Party other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@id == other.__isset.@id) && ((!__isset.@id) || (global::System.Object.Equals(Id, other.Id)))) + && ((__isset.@name == other.__isset.@name) && ((!__isset.@name) || (global::System.Object.Equals(Name, other.Name)))) + && ((__isset.taxId == other.__isset.taxId) && ((!__isset.taxId) || (global::System.Object.Equals(TaxId, other.TaxId)))) + && ((__isset.@email == other.__isset.@email) && ((!__isset.@email) || (global::System.Object.Equals(Email, other.Email)))) + && ((__isset.@phone == other.__isset.@phone) && ((!__isset.@phone) || (global::System.Object.Equals(Phone, other.Phone)))) + && ((__isset.@address == other.__isset.@address) && ((!__isset.@address) || (global::System.Object.Equals(Address, other.Address)))) + && ((__isset.preferredLanguage == other.__isset.preferredLanguage) && ((!__isset.preferredLanguage) || (global::System.Object.Equals(PreferredLanguage, other.PreferredLanguage)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@id) + { + hashcode = (hashcode * 397) + Id.GetHashCode(); + } + if((Name != null) && __isset.@name) + { + hashcode = (hashcode * 397) + Name.GetHashCode(); + } + if((TaxId != null) && __isset.taxId) + { + hashcode = (hashcode * 397) + TaxId.GetHashCode(); + } + if((Email != null) && __isset.@email) + { + hashcode = (hashcode * 397) + Email.GetHashCode(); + } + if((Phone != null) && __isset.@phone) + { + hashcode = (hashcode * 397) + Phone.GetHashCode(); + } + if((Address != null) && __isset.@address) + { + hashcode = (hashcode * 397) + Address.GetHashCode(); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + hashcode = (hashcode * 397) + PreferredLanguage.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp23 = new StringBuilder("Party("); + int tmp24 = 0; + if(__isset.@id) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Id: "); + Id.ToString(tmp23); + } + if((Name != null) && __isset.@name) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Name: "); + Name.ToString(tmp23); + } + if((TaxId != null) && __isset.taxId) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("TaxId: "); + TaxId.ToString(tmp23); + } + if((Email != null) && __isset.@email) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Email: "); + Email.ToString(tmp23); + } + if((Phone != null) && __isset.@phone) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Phone: "); + Phone.ToString(tmp23); + } + if((Address != null) && __isset.@address) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("Address: "); + Address.ToString(tmp23); + } + if((PreferredLanguage != null) && __isset.preferredLanguage) + { + if(0 < tmp24++) { tmp23.Append(", "); } + tmp23.Append("PreferredLanguage: "); + PreferredLanguage.ToString(tmp23); + } + tmp23.Append(')'); + return tmp23.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Payment.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Payment.cs new file mode 100644 index 0000000..36ccf56 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Payment.cs @@ -0,0 +1,436 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Payment : TBase + { + private global::Echo.ThriftModel.PaymentMethod _method; + private double _amount; + private string _reference; + private long _timestamp; + private double _fee; + private global::Echo.ThriftModel.Currency _currency; + + /// + /// + /// + /// + public global::Echo.ThriftModel.PaymentMethod Method + { + get + { + return _method; + } + set + { + __isset.@method = true; + this._method = value; + } + } + + public double Amount + { + get + { + return _amount; + } + set + { + __isset.@amount = true; + this._amount = value; + } + } + + public string Reference + { + get + { + return _reference; + } + set + { + __isset.@reference = true; + this._reference = value; + } + } + + public long Timestamp + { + get + { + return _timestamp; + } + set + { + __isset.@timestamp = true; + this._timestamp = value; + } + } + + public double Fee + { + get + { + return _fee; + } + set + { + __isset.@fee = true; + this._fee = value; + } + } + + /// + /// + /// + /// + public global::Echo.ThriftModel.Currency Currency + { + get + { + return _currency; + } + set + { + __isset.@currency = true; + this._currency = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @method; + public bool @amount; + public bool @reference; + public bool @timestamp; + public bool @fee; + public bool @currency; + } + + public Payment() + { + } + + public Payment DeepCopy() + { + var tmp45 = new Payment(); + if(__isset.@method) + { + tmp45.Method = this.Method; + } + tmp45.__isset.@method = this.__isset.@method; + if(__isset.@amount) + { + tmp45.Amount = this.Amount; + } + tmp45.__isset.@amount = this.__isset.@amount; + if((Reference != null) && __isset.@reference) + { + tmp45.Reference = this.Reference; + } + tmp45.__isset.@reference = this.__isset.@reference; + if(__isset.@timestamp) + { + tmp45.Timestamp = this.Timestamp; + } + tmp45.__isset.@timestamp = this.__isset.@timestamp; + if(__isset.@fee) + { + tmp45.Fee = this.Fee; + } + tmp45.__isset.@fee = this.__isset.@fee; + if(__isset.@currency) + { + tmp45.Currency = this.Currency; + } + tmp45.__isset.@currency = this.__isset.@currency; + return tmp45; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + Method = (global::Echo.ThriftModel.PaymentMethod)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Double) + { + Amount = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.String) + { + Reference = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + Timestamp = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + Fee = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.I32) + { + Currency = (global::Echo.ThriftModel.Currency)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp46 = new TStruct("Payment"); + await oprot.WriteStructBeginAsync(tmp46, cancellationToken); + var tmp47 = new TField(); + if(__isset.@method) + { + tmp47.Name = "method"; + tmp47.Type = TType.I32; + tmp47.ID = 1; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI32Async((int)Method, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@amount) + { + tmp47.Name = "amount"; + tmp47.Type = TType.Double; + tmp47.ID = 2; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteDoubleAsync(Amount, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((Reference != null) && __isset.@reference) + { + tmp47.Name = "reference"; + tmp47.Type = TType.String; + tmp47.ID = 3; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteStringAsync(Reference, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@timestamp) + { + tmp47.Name = "timestamp"; + tmp47.Type = TType.I64; + tmp47.ID = 4; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI64Async(Timestamp, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@fee) + { + tmp47.Name = "fee"; + tmp47.Type = TType.Double; + tmp47.ID = 5; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteDoubleAsync(Fee, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.@currency) + { + tmp47.Name = "currency"; + tmp47.Type = TType.I32; + tmp47.ID = 6; + await oprot.WriteFieldBeginAsync(tmp47, cancellationToken); + await oprot.WriteI32Async((int)Currency, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Payment other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@method == other.__isset.@method) && ((!__isset.@method) || (global::System.Object.Equals(Method, other.Method)))) + && ((__isset.@amount == other.__isset.@amount) && ((!__isset.@amount) || (global::System.Object.Equals(Amount, other.Amount)))) + && ((__isset.@reference == other.__isset.@reference) && ((!__isset.@reference) || (global::System.Object.Equals(Reference, other.Reference)))) + && ((__isset.@timestamp == other.__isset.@timestamp) && ((!__isset.@timestamp) || (global::System.Object.Equals(Timestamp, other.Timestamp)))) + && ((__isset.@fee == other.__isset.@fee) && ((!__isset.@fee) || (global::System.Object.Equals(Fee, other.Fee)))) + && ((__isset.@currency == other.__isset.@currency) && ((!__isset.@currency) || (global::System.Object.Equals(Currency, other.Currency)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@method) + { + hashcode = (hashcode * 397) + Method.GetHashCode(); + } + if(__isset.@amount) + { + hashcode = (hashcode * 397) + Amount.GetHashCode(); + } + if((Reference != null) && __isset.@reference) + { + hashcode = (hashcode * 397) + Reference.GetHashCode(); + } + if(__isset.@timestamp) + { + hashcode = (hashcode * 397) + Timestamp.GetHashCode(); + } + if(__isset.@fee) + { + hashcode = (hashcode * 397) + Fee.GetHashCode(); + } + if(__isset.@currency) + { + hashcode = (hashcode * 397) + Currency.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp48 = new StringBuilder("Payment("); + int tmp49 = 0; + if(__isset.@method) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Method: "); + Method.ToString(tmp48); + } + if(__isset.@amount) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Amount: "); + Amount.ToString(tmp48); + } + if((Reference != null) && __isset.@reference) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Reference: "); + Reference.ToString(tmp48); + } + if(__isset.@timestamp) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Timestamp: "); + Timestamp.ToString(tmp48); + } + if(__isset.@fee) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Fee: "); + Fee.ToString(tmp48); + } + if(__isset.@currency) + { + if(0 < tmp49++) { tmp48.Append(", "); } + tmp48.Append("Currency: "); + Currency.ToString(tmp48); + } + tmp48.Append(')'); + return tmp48.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/PaymentMethod.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/PaymentMethod.cs new file mode 100644 index 0000000..f1cdc92 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/PaymentMethod.cs @@ -0,0 +1,25 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public enum PaymentMethod + { + Cash = 0, + Card = 1, + Wire = 2, + Crypto = 3, + Other = 4, + } +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Variant.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Variant.cs new file mode 100644 index 0000000..935f322 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/Variant.cs @@ -0,0 +1,582 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; +using Thrift.Transport.Client; +using Thrift.Transport.Server; +using Thrift.Processor; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + + public partial class Variant : TBase + { + private global::Echo.ThriftModel.Kind _tag; + private bool _boolVal; + private long _i64Val; + private long _u64Val; + private double _f64Val; + private string _strVal; + private byte[] _bytesVal; + private long _dtVal; + private byte[] _guidVal; + + /// + /// + /// + /// + public global::Echo.ThriftModel.Kind Tag + { + get + { + return _tag; + } + set + { + __isset.@tag = true; + this._tag = value; + } + } + + public bool BoolVal + { + get + { + return _boolVal; + } + set + { + __isset.boolVal = true; + this._boolVal = value; + } + } + + public long I64Val + { + get + { + return _i64Val; + } + set + { + __isset.i64Val = true; + this._i64Val = value; + } + } + + public long U64Val + { + get + { + return _u64Val; + } + set + { + __isset.u64Val = true; + this._u64Val = value; + } + } + + public double F64Val + { + get + { + return _f64Val; + } + set + { + __isset.f64Val = true; + this._f64Val = value; + } + } + + public string StrVal + { + get + { + return _strVal; + } + set + { + __isset.strVal = true; + this._strVal = value; + } + } + + public byte[] BytesVal + { + get + { + return _bytesVal; + } + set + { + __isset.bytesVal = true; + this._bytesVal = value; + } + } + + public long DtVal + { + get + { + return _dtVal; + } + set + { + __isset.dtVal = true; + this._dtVal = value; + } + } + + public byte[] GuidVal + { + get + { + return _guidVal; + } + set + { + __isset.guidVal = true; + this._guidVal = value; + } + } + + + public Isset __isset; + public struct Isset + { + public bool @tag; + public bool boolVal; + public bool i64Val; + public bool u64Val; + public bool f64Val; + public bool strVal; + public bool bytesVal; + public bool dtVal; + public bool guidVal; + } + + public Variant() + { + } + + public Variant DeepCopy() + { + var tmp0 = new Variant(); + if(__isset.@tag) + { + tmp0.Tag = this.Tag; + } + tmp0.__isset.@tag = this.__isset.@tag; + if(__isset.boolVal) + { + tmp0.BoolVal = this.BoolVal; + } + tmp0.__isset.boolVal = this.__isset.boolVal; + if(__isset.i64Val) + { + tmp0.I64Val = this.I64Val; + } + tmp0.__isset.i64Val = this.__isset.i64Val; + if(__isset.u64Val) + { + tmp0.U64Val = this.U64Val; + } + tmp0.__isset.u64Val = this.__isset.u64Val; + if(__isset.f64Val) + { + tmp0.F64Val = this.F64Val; + } + tmp0.__isset.f64Val = this.__isset.f64Val; + if((StrVal != null) && __isset.strVal) + { + tmp0.StrVal = this.StrVal; + } + tmp0.__isset.strVal = this.__isset.strVal; + if((BytesVal != null) && __isset.bytesVal) + { + tmp0.BytesVal = this.BytesVal.ToArray(); + } + tmp0.__isset.bytesVal = this.__isset.bytesVal; + if(__isset.dtVal) + { + tmp0.DtVal = this.DtVal; + } + tmp0.__isset.dtVal = this.__isset.dtVal; + if((GuidVal != null) && __isset.guidVal) + { + tmp0.GuidVal = this.GuidVal.ToArray(); + } + tmp0.__isset.guidVal = this.__isset.guidVal; + return tmp0; + } + + public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken) + { + iprot.IncrementRecursionDepth(); + try + { + TField field; + await iprot.ReadStructBeginAsync(cancellationToken); + while (true) + { + field = await iprot.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.I32) + { + Tag = (global::Echo.ThriftModel.Kind)await iprot.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 2: + if (field.Type == TType.Bool) + { + BoolVal = await iprot.ReadBoolAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 3: + if (field.Type == TType.I64) + { + I64Val = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 4: + if (field.Type == TType.I64) + { + U64Val = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 5: + if (field.Type == TType.Double) + { + F64Val = await iprot.ReadDoubleAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 6: + if (field.Type == TType.String) + { + StrVal = await iprot.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 7: + if (field.Type == TType.String) + { + BytesVal = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 8: + if (field.Type == TType.I64) + { + DtVal = await iprot.ReadI64Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + case 9: + if (field.Type == TType.String) + { + GuidVal = await iprot.ReadBinaryAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken); + break; + } + + await iprot.ReadFieldEndAsync(cancellationToken); + } + + await iprot.ReadStructEndAsync(cancellationToken); + } + finally + { + iprot.DecrementRecursionDepth(); + } + } + + public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var tmp1 = new TStruct("Variant"); + await oprot.WriteStructBeginAsync(tmp1, cancellationToken); + var tmp2 = new TField(); + if(__isset.@tag) + { + tmp2.Name = "tag"; + tmp2.Type = TType.I32; + tmp2.ID = 1; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI32Async((int)Tag, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.boolVal) + { + tmp2.Name = "boolVal"; + tmp2.Type = TType.Bool; + tmp2.ID = 2; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBoolAsync(BoolVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.i64Val) + { + tmp2.Name = "i64Val"; + tmp2.Type = TType.I64; + tmp2.ID = 3; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(I64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.u64Val) + { + tmp2.Name = "u64Val"; + tmp2.Type = TType.I64; + tmp2.ID = 4; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(U64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.f64Val) + { + tmp2.Name = "f64Val"; + tmp2.Type = TType.Double; + tmp2.ID = 5; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteDoubleAsync(F64Val, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((StrVal != null) && __isset.strVal) + { + tmp2.Name = "strVal"; + tmp2.Type = TType.String; + tmp2.ID = 6; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteStringAsync(StrVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((BytesVal != null) && __isset.bytesVal) + { + tmp2.Name = "bytesVal"; + tmp2.Type = TType.String; + tmp2.ID = 7; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBinaryAsync(BytesVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if(__isset.dtVal) + { + tmp2.Name = "dtVal"; + tmp2.Type = TType.I64; + tmp2.ID = 8; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteI64Async(DtVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + if((GuidVal != null) && __isset.guidVal) + { + tmp2.Name = "guidVal"; + tmp2.Type = TType.String; + tmp2.ID = 9; + await oprot.WriteFieldBeginAsync(tmp2, cancellationToken); + await oprot.WriteBinaryAsync(GuidVal, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override bool Equals(object that) + { + if (!(that is Variant other)) return false; + if (ReferenceEquals(this, other)) return true; + return ((__isset.@tag == other.__isset.@tag) && ((!__isset.@tag) || (global::System.Object.Equals(Tag, other.Tag)))) + && ((__isset.boolVal == other.__isset.boolVal) && ((!__isset.boolVal) || (global::System.Object.Equals(BoolVal, other.BoolVal)))) + && ((__isset.i64Val == other.__isset.i64Val) && ((!__isset.i64Val) || (global::System.Object.Equals(I64Val, other.I64Val)))) + && ((__isset.u64Val == other.__isset.u64Val) && ((!__isset.u64Val) || (global::System.Object.Equals(U64Val, other.U64Val)))) + && ((__isset.f64Val == other.__isset.f64Val) && ((!__isset.f64Val) || (global::System.Object.Equals(F64Val, other.F64Val)))) + && ((__isset.strVal == other.__isset.strVal) && ((!__isset.strVal) || (global::System.Object.Equals(StrVal, other.StrVal)))) + && ((__isset.bytesVal == other.__isset.bytesVal) && ((!__isset.bytesVal) || (TCollections.Equals(BytesVal, other.BytesVal)))) + && ((__isset.dtVal == other.__isset.dtVal) && ((!__isset.dtVal) || (global::System.Object.Equals(DtVal, other.DtVal)))) + && ((__isset.guidVal == other.__isset.guidVal) && ((!__isset.guidVal) || (TCollections.Equals(GuidVal, other.GuidVal)))); + } + + public override int GetHashCode() { + int hashcode = 157; + unchecked { + if(__isset.@tag) + { + hashcode = (hashcode * 397) + Tag.GetHashCode(); + } + if(__isset.boolVal) + { + hashcode = (hashcode * 397) + BoolVal.GetHashCode(); + } + if(__isset.i64Val) + { + hashcode = (hashcode * 397) + I64Val.GetHashCode(); + } + if(__isset.u64Val) + { + hashcode = (hashcode * 397) + U64Val.GetHashCode(); + } + if(__isset.f64Val) + { + hashcode = (hashcode * 397) + F64Val.GetHashCode(); + } + if((StrVal != null) && __isset.strVal) + { + hashcode = (hashcode * 397) + StrVal.GetHashCode(); + } + if((BytesVal != null) && __isset.bytesVal) + { + hashcode = (hashcode * 397) + BytesVal.GetHashCode(); + } + if(__isset.dtVal) + { + hashcode = (hashcode * 397) + DtVal.GetHashCode(); + } + if((GuidVal != null) && __isset.guidVal) + { + hashcode = (hashcode * 397) + GuidVal.GetHashCode(); + } + } + return hashcode; + } + + public override string ToString() + { + var tmp3 = new StringBuilder("Variant("); + int tmp4 = 0; + if(__isset.@tag) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("Tag: "); + Tag.ToString(tmp3); + } + if(__isset.boolVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("BoolVal: "); + BoolVal.ToString(tmp3); + } + if(__isset.i64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("I64Val: "); + I64Val.ToString(tmp3); + } + if(__isset.u64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("U64Val: "); + U64Val.ToString(tmp3); + } + if(__isset.f64Val) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("F64Val: "); + F64Val.ToString(tmp3); + } + if((StrVal != null) && __isset.strVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("StrVal: "); + StrVal.ToString(tmp3); + } + if((BytesVal != null) && __isset.bytesVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("BytesVal: "); + BytesVal.ToString(tmp3); + } + if(__isset.dtVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("DtVal: "); + DtVal.ToString(tmp3); + } + if((GuidVal != null) && __isset.guidVal) + { + if(0 < tmp4++) { tmp3.Append(", "); } + tmp3.Append("GuidVal: "); + GuidVal.ToString(tmp3); + } + tmp3.Append(')'); + return tmp3.ToString(); + } + } + +} diff --git a/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/echo.Extensions.cs b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/echo.Extensions.cs new file mode 100644 index 0000000..4d5aed8 --- /dev/null +++ b/Tests/RPC/Thrift/gen-netstd/Echo/ThriftModel/echo.Extensions.cs @@ -0,0 +1,276 @@ +/** + * + * Autogenerated by Thrift Compiler (0.19.0) + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocol; + + +#pragma warning disable IDE0079 // remove unnecessary pragmas +#pragma warning disable IDE0017 // object init can be simplified +#pragma warning disable IDE0028 // collection init can be simplified +#pragma warning disable IDE1006 // parts of the code use IDL spelling +#pragma warning disable CA1822 // empty DeepCopy() methods still non-static +#pragma warning disable IDE0083 // pattern matching "that is not SomeType" requires net5.0 but we still support earlier versions + +namespace Echo.ThriftModel +{ + public static class echoExtensions + { + public static bool Equals(this Dictionary instance, object that) + { + if (!(that is Dictionary other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this Dictionary instance) + { + return TCollections.GetHashCode(instance); + } + + + public static Dictionary DeepCopy(this Dictionary source) + { + if (source == null) + return null; + + var tmp232 = new Dictionary(source.Count); + foreach (var pair in source) + tmp232.Add((pair.Key != null) ? pair.Key : null, (pair.Value != null) ? pair.Value.DeepCopy() : null); + return tmp232; + } + + + public static bool Equals(this Dictionary instance, object that) + { + if (!(that is Dictionary other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this Dictionary instance) + { + return TCollections.GetHashCode(instance); + } + + + public static Dictionary DeepCopy(this Dictionary source) + { + if (source == null) + return null; + + var tmp233 = new Dictionary(source.Count); + foreach (var pair in source) + tmp233.Add((pair.Key != null) ? pair.Key : null, (pair.Value != null) ? pair.Value.DeepCopy() : null); + return tmp233; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp234 = new List(source.Count); + foreach (var elem in source) + tmp234.Add((elem != null) ? elem.DeepCopy() : null); + return tmp234; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp235 = new List(source.Count); + foreach (var elem in source) + tmp235.Add((elem != null) ? elem.DeepCopy() : null); + return tmp235; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp236 = new List(source.Count); + foreach (var elem in source) + tmp236.Add(elem); + return tmp236; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp237 = new List(source.Count); + foreach (var elem in source) + tmp237.Add((elem != null) ? elem.DeepCopy() : null); + return tmp237; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp238 = new List(source.Count); + foreach (var elem in source) + tmp238.Add((elem != null) ? elem.DeepCopy() : null); + return tmp238; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp239 = new List(source.Count); + foreach (var elem in source) + tmp239.Add(elem); + return tmp239; + } + + + public static bool Equals(this List instance, object that) + { + if (!(that is List other)) return false; + if (ReferenceEquals(instance, other)) return true; + + return TCollections.Equals(instance, other); + } + + + public static int GetHashCode(this List instance) + { + return TCollections.GetHashCode(instance); + } + + + public static List DeepCopy(this List source) + { + if (source == null) + return null; + + var tmp240 = new List(source.Count); + foreach (var elem in source) + tmp240.Add((elem != null) ? elem : null); + return tmp240; + } + + + } +} diff --git a/Tests/RPC/gRPC/EchoImp.cs b/Tests/RPC/gRPC/EchoImp.cs new file mode 100644 index 0000000..677358b --- /dev/null +++ b/Tests/RPC/gRPC/EchoImp.cs @@ -0,0 +1,59 @@ +using Echo.Model.Grpc; +using Google.Protobuf; +using Google.Protobuf.Collections; +using Grpc.Core; +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using static Echo.Model.Grpc.EchoService; + +namespace Echo +{ + public class EchoServiceImpl : EchoServiceBase + { + public override Task EchoBytes(BytesRequest request, ServerCallContext context) + { + var rt = new BytesResponse(); + rt.Data = ByteString.CopyFrom(request.Data.ToArray()); + return Task.FromResult(rt); + } + + public override Task EchoDocuments(DocumentsRequest request, ServerCallContext context) + { + var rt = new DocumentsResponse(); + rt.Docs.AddRange(request.Docs); + return Task.FromResult(rt); + } + + public override Task EchoEnumArray(EnumArrayRequest request, ServerCallContext context) + { + var rt = new EnumResponse(); + rt.DocTypes.AddRange(request.DocTypes); + return Task.FromResult(rt); + } + + public override Task EchoIntArray(IntArrayRequest request, ServerCallContext context) + { + var rt = new IntArrayResponse(); + rt.Array.AddRange(request.Array); + return Task.FromResult(rt); + } + + public override Task EchoMap(DocMapRequest request, ServerCallContext context) + { + var rt = new DocMapResponse(); + foreach(var kv in request.Map) + rt.Map.Add(kv.Key, kv.Value); + + return Task.FromResult(rt); + } + + public override Task EchoStringArray(StringArrayRequest request, ServerCallContext context) + { + var rt = new StringArrayResponse(); + rt.Array.AddRange(request.Array); + return Task.FromResult(rt); + } + } +} \ No newline at end of file diff --git a/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.csproj b/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.csproj new file mode 100644 index 0000000..fc28233 --- /dev/null +++ b/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.csproj @@ -0,0 +1,25 @@ + + + + net10.0 + enable + enable + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.http b/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.http new file mode 100644 index 0000000..931a1ab --- /dev/null +++ b/Tests/RPC/gRPC/Esiur.Tests.RPC.GrpcServer.http @@ -0,0 +1,6 @@ +@RPC.gRPC_HostAddress = http://localhost:5193 + +GET {{RPC.gRPC_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Tests/RPC/gRPC/Program.cs b/Tests/RPC/gRPC/Program.cs new file mode 100644 index 0000000..edc3288 --- /dev/null +++ b/Tests/RPC/gRPC/Program.cs @@ -0,0 +1,18 @@ + + +using Echo; +using Microsoft.AspNetCore.Server.Kestrel.Core; + +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.ConfigureKestrel(o => +{ + // Listen on 5300 and force HTTP/2 (h2c) + o.ListenAnyIP(5300, lo => lo.Protocols = HttpProtocols.Http2); +}); + +builder.Services.AddGrpc(); +var app = builder.Build(); +app.MapGrpcService(); +app.Urls.Add("http://0.0.0.0:5300"); +app.Run(); \ No newline at end of file diff --git a/Tests/RPC/gRPC/Properties/launchSettings.json b/Tests/RPC/gRPC/Properties/launchSettings.json new file mode 100644 index 0000000..7d6108f --- /dev/null +++ b/Tests/RPC/gRPC/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5193", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7236;http://localhost:5193", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Tests/RPC/gRPC/appsettings.Development.json b/Tests/RPC/gRPC/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Tests/RPC/gRPC/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Tests/RPC/gRPC/appsettings.json b/Tests/RPC/gRPC/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Tests/RPC/gRPC/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Tests/RPC/gRPC/echo.proto b/Tests/RPC/gRPC/echo.proto new file mode 100644 index 0000000..84b1c07 --- /dev/null +++ b/Tests/RPC/gRPC/echo.proto @@ -0,0 +1,244 @@ +syntax = "proto3"; + +package gpmodel; + +option csharp_namespace = "Echo.Model.Grpc"; + +// ========================= Enums ========================= + +enum Currency { + CURRENCY_IQD = 0; + CURRENCY_CNH = 1; + CURRENCY_USD = 2; + CURRENCY_EUR = 3; + CURRENCY_JPY = 4; + CURRENCY_GBP = 5; +} + +enum DocType { + DOC_TYPE_QUOTE = 0; + DOC_TYPE_ORDER = 1; + DOC_TYPE_INVOICE = 2; + DOC_TYPE_CREDIT_NOTE = 3; +} + +enum PaymentMethod { + PAYMENT_METHOD_CASH = 0; + PAYMENT_METHOD_CARD = 1; + PAYMENT_METHOD_WIRE = 2; + PAYMENT_METHOD_CRYPTO = 3; + PAYMENT_METHOD_OTHER = 4; +} + +enum LineType { + LINE_TYPE_PRODUCT = 0; + LINE_TYPE_SERVICE = 1; + LINE_TYPE_DISCOUNT = 2; + LINE_TYPE_SHIPPING = 3; +} + +// Variant.Kind +enum Kind { + KIND_NULL = 0; + KIND_BOOL = 1; + KIND_INT64 = 2; + KIND_UINT64 = 3; + KIND_DOUBLE = 4; + KIND_DECIMAL = 5; + KIND_STRING = 6; + KIND_BYTES = 7; + KIND_DATETIME = 8; + KIND_GUID = 9; +} + +// ========================= Variant ========================= +// +// C# Variant: +// Tag: Kind +// Bool: bool? +// I64: long? +// U64: ulong? +// F64: double? +// Str: string? +// Bytes: byte[]? +// Dt: DateTime? -> int64 (ticks or epoch millis) +// Guid: byte[]? + +message Variant { + Kind tag = 1; + bool bool_val = 2; // optional in C# + int64 i64_val = 3; // optional in C# + uint64 u64_val = 4; // optional in C# + double f64_val = 5; // optional in C# + string str_val = 6; // optional in C# + bytes bytes_val = 7; // optional in C# + int64 dt_val = 8; // optional in C# (DateTime) + bytes guid_val = 9; // optional in C# (Guid as 16-byte array) +} + +// Optional helpers mirroring MetaEntry / ExtEntry (not required for RPC) +message MetaEntry { + string key = 1; + Variant value = 2; +} + +message ExtEntry { + string key = 1; + Variant value = 2; +} + +// ========================= Address & Party ========================= + +message Address { + string line1 = 1; + string line2 = 2; // optional in C# + string city = 3; + string region = 4; + string country = 5; + string postal_code = 6; // optional in C# +} + +message Party { + uint64 id = 1; + string name = 2; + string tax_id = 3; // optional in C# + string email = 4; // optional in C# + string phone = 5; // optional in C# + Address address = 6; // optional in C# + string preferred_language = 7; // optional in C# +} + +// ========================= DocumentHeader ========================= +// +// DateTime/DateTime? -> int64 (ticks or epoch millis, your choice) + +message DocumentHeader { + bytes doc_id = 1; + DocType type = 2; + int32 version = 3; + int64 created_at = 4; // DateTime + int64 updated_at = 5; // optional in C# + Currency currency = 6; + string notes = 7; // optional in C# + map meta = 8; +} + +// ========================= LineItem, Payment, Attachment ========================= + +message LineItem { + int32 line_no = 1; + LineType type = 2; + string sku = 3; + string description = 4; + double qty = 5; + string qty_unit = 6; + double unit_price = 7; + double vat_rate = 8; // optional in C# + double discount = 9; // optional in C# + map ext = 10; +} + +message Payment { + PaymentMethod method = 1; + double amount = 2; + string reference = 3; // optional in C# + int64 timestamp = 4; // DateTime + double fee = 5; // optional in C# + Currency currency = 6; +} + +message Attachment { + string name = 1; + string mime_type = 2; + bytes data = 3; +} + +// ========================= Top-level BusinessDocument ========================= + +message BusinessDocument { + DocumentHeader header = 1; + Party seller = 2; + Party buyer = 3; + repeated LineItem items = 4; + repeated Payment payments = 5; + repeated Attachment attachments = 6; + repeated int32 risk_scores = 7; +} + +// ========================= Echo Service Messages ========================= +// +// C# signatures: +// +// byte[] EchoBytes(byte[]) +// BusinessDocument[] EchoDocuments(BusinessDocument[] docs) +// int[] EchoIntArray(int[] array) +// string[] EchoStringArray(string[] array) +// Map EchoMap(Map map) +// DocType EchoEnumArray(DocType[] docTypes); + +// --- Bytes --- +message BytesRequest { + bytes data = 1; +} + +// --- Bytes --- +message BytesResponse { + bytes data = 1; +} + + +// --- Documents --- +message DocumentsRequest { + repeated BusinessDocument docs = 1; +} + +message DocumentsResponse { + repeated BusinessDocument docs = 1; +} + +// --- Int array --- +message IntArrayRequest { + repeated int32 array = 1; +} + +message IntArrayResponse { + repeated int32 array = 1; +} + +// --- String array --- +message StringArrayRequest { + repeated string array = 1; +} + +message StringArrayResponse { + repeated string array = 1; +} + +// --- Map --- +message DocMapRequest { + map map = 1; +} + +message DocMapResponse { + map map = 1; +} + +// --- Enum array (returns a single DocType, e.g. last element) --- +message EnumArrayRequest { + repeated DocType doc_types = 1; +} + +message EnumResponse { + repeated DocType doc_types = 1; +} + +// ========================= Echo Service ========================= + +service EchoService { + rpc EchoBytes (BytesRequest) returns (BytesResponse); + rpc EchoDocuments (DocumentsRequest) returns (DocumentsResponse); + rpc EchoIntArray (IntArrayRequest) returns (IntArrayResponse); + rpc EchoStringArray (StringArrayRequest) returns (StringArrayResponse); + rpc EchoMap (DocMapRequest) returns (DocMapResponse); + rpc EchoEnumArray (EnumArrayRequest) returns (EnumResponse); +} diff --git a/Tests/RPC/gRPC/libman.json b/Tests/RPC/gRPC/libman.json new file mode 100644 index 0000000..8ed1410 --- /dev/null +++ b/Tests/RPC/gRPC/libman.json @@ -0,0 +1,5 @@ +{ + "version": "3.0", + "defaultProvider": "cdnjs", + "libraries": [] +} \ No newline at end of file diff --git a/Tests/Serialization/ComplexObject/ModelRunner.cs b/Tests/Serialization/ComplexObject/ModelRunner.cs index a9f4da9..9d15e36 100644 --- a/Tests/Serialization/ComplexObject/ModelRunner.cs +++ b/Tests/Serialization/ComplexObject/ModelRunner.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -377,6 +378,8 @@ public sealed class ModelRunner var jsonMean = Stats.Mean(jsonSizes); var jsonMed = Stats.Median(jsonSizes); + var st = new StringBuilder(); + Console.WriteLine($"JSON mean: {jsonMean:F1} B, median: {jsonMed:F1} B"); Console.WriteLine(); @@ -384,6 +387,8 @@ public sealed class ModelRunner "Codec", "Mean(B)", "Median(B)", "Ratio", "Reduction", "Enc CPU (µs)", "Dec CPU (µs)"); Console.WriteLine(new string('-', 118)); + st.AppendLine("Codec,Mean(B),Median(B),Ratio,Reduction"); + foreach (var c in _codecs) { var r = results[c.Name]; @@ -406,11 +411,13 @@ public sealed class ModelRunner Console.WriteLine("{0,-14} {1,12} {2,12} {3,10} {4,26} {5,18} {6,18}", c.Name, meanS, medS, ratioS, reduction, encCpuS, decCpuS); + + st.AppendLine($"{c.Name},{meanS},{medS},{ratioS},{reduction}"); } Console.WriteLine(); - //Console.ReadLine(); + File.AppendAllLines("complex_model_results.csv", st.ToString().Split(Environment.NewLine)); } }