From 9a121245744390dce565adda3f8c9b594e3c13c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Sat, 19 Oct 2019 16:39:16 +0200 Subject: [PATCH] Issue #20 --- .../Capnp.Net.Runtime.Tests.Core21.csproj | 1 + .../DynamicSerializerStateTests.cs | 36 ++- Capnp.Net.Runtime.Tests/Issue20.cs | 219 ++++++++++++++++++ Capnp.Net.Runtime/SerializerState.cs | 55 ++--- 4 files changed, 284 insertions(+), 27 deletions(-) create mode 100644 Capnp.Net.Runtime.Tests/Issue20.cs diff --git a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj index 2e1fffa..2492433 100644 --- a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj +++ b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj @@ -15,6 +15,7 @@ + diff --git a/Capnp.Net.Runtime.Tests/DynamicSerializerStateTests.cs b/Capnp.Net.Runtime.Tests/DynamicSerializerStateTests.cs index 5a58ee5..0797860 100644 --- a/Capnp.Net.Runtime.Tests/DynamicSerializerStateTests.cs +++ b/Capnp.Net.Runtime.Tests/DynamicSerializerStateTests.cs @@ -1,6 +1,8 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using CapnpGen; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.IO; namespace Capnp.Net.Runtime.Tests { @@ -923,5 +925,37 @@ namespace Capnp.Net.Runtime.Tests } } } + + [TestMethod] + public void Issue20() + { + RpcRequest rpcRequest = new RpcRequest(); + rpcRequest.Method = "AddTwoNumbers"; + + ArithmeticOperationRequest request = new ArithmeticOperationRequest(); + + request.NumA = 5; + request.NumB = 8; + + rpcRequest.Request = request; + + var msg = MessageBuilder.Create(); + var root = msg.BuildRoot.WRITER>(); + rpcRequest.serialize(root); + + var mems = new MemoryStream(); + var pump = new FramePump(mems); + pump.Send(msg.Frame); + mems.Seek(0, SeekOrigin.Begin); + + var frame = Framing.ReadSegments(mems); + var deserializer = DeserializerState.CreateRoot(frame); + var mainRequest = new RpcRequest.READER(deserializer); + var innerRequest = new ArithmeticOperationRequest.READER(mainRequest.Request); + + Console.WriteLine("Method Name: " + mainRequest.Method); + Console.WriteLine("NumA: " + innerRequest.NumA.ToString()); + Console.WriteLine("NumB: " + innerRequest.NumB.ToString()); + } } } diff --git a/Capnp.Net.Runtime.Tests/Issue20.cs b/Capnp.Net.Runtime.Tests/Issue20.cs new file mode 100644 index 0000000..e82ffbf --- /dev/null +++ b/Capnp.Net.Runtime.Tests/Issue20.cs @@ -0,0 +1,219 @@ +using Capnp; +using Capnp.Rpc; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace CapnpGen +{ + [TypeId(0xb706e295e5860f3dUL)] + public class RpcRequest : ICapnpSerializable where TRequest : class + { + public const UInt64 typeId = 0xb706e295e5860f3dUL; + void ICapnpSerializable.Deserialize(DeserializerState arg_) + { + var reader = READER.create(arg_); + Method = reader.Method; + Request = CapnpSerializable.Create(reader.Request); + applyDefaults(); + } + + public void serialize(WRITER writer) + { + writer.Method = Method; + writer.Request.SetObject(Request); + } + + void ICapnpSerializable.Serialize(SerializerState arg_) + { + serialize(arg_.Rewrap()); + } + + public void applyDefaults() + { + } + + public string Method + { + get; + set; + } + + public TRequest Request + { + get; + set; + } + + public struct READER + { + readonly DeserializerState ctx; + public READER(DeserializerState ctx) + { + this.ctx = ctx; + } + + public static READER create(DeserializerState ctx) => new READER(ctx); + public static implicit operator DeserializerState(READER reader) => reader.ctx; + public static implicit operator READER(DeserializerState ctx) => new READER(ctx); + public string Method => ctx.ReadText(0, ""); + public DeserializerState Request => ctx.StructReadPointer(1); + } + + public class WRITER : SerializerState + { + public WRITER() + { + this.SetStruct(0, 2); + } + + public string Method + { + get => this.ReadText(0, ""); + set => this.WriteText(0, value, ""); + } + + public DynamicSerializerState Request + { + get => BuildPointer(1); + set => Link(1, value); + } + } + } + + [TypeId(0xca749dac8d513c9fUL)] + public class ArithmeticOperationRequest : ICapnpSerializable + { + public const UInt64 typeId = 0xca749dac8d513c9fUL; + void ICapnpSerializable.Deserialize(DeserializerState arg_) + { + var reader = READER.create(arg_); + NumA = reader.NumA; + NumB = reader.NumB; + applyDefaults(); + } + + public void serialize(WRITER writer) + { + writer.NumA = NumA; + writer.NumB = NumB; + } + + void ICapnpSerializable.Serialize(SerializerState arg_) + { + serialize(arg_.Rewrap()); + } + + public void applyDefaults() + { + } + + public int NumA + { + get; + set; + } + + public int NumB + { + get; + set; + } + + public struct READER + { + readonly DeserializerState ctx; + public READER(DeserializerState ctx) + { + this.ctx = ctx; + } + + public static READER create(DeserializerState ctx) => new READER(ctx); + public static implicit operator DeserializerState(READER reader) => reader.ctx; + public static implicit operator READER(DeserializerState ctx) => new READER(ctx); + public int NumA => ctx.ReadDataInt(0UL, 0); + public int NumB => ctx.ReadDataInt(32UL, 0); + } + + public class WRITER : SerializerState + { + public WRITER() + { + this.SetStruct(1, 0); + } + + public int NumA + { + get => this.ReadDataInt(0UL, 0); + set => this.WriteData(0UL, value, 0); + } + + public int NumB + { + get => this.ReadDataInt(32UL, 0); + set => this.WriteData(32UL, value, 0); + } + } + } + + [TypeId(0xc64f52df07418506UL)] + public class ArithmeticOperationReply : ICapnpSerializable + { + public const UInt64 typeId = 0xc64f52df07418506UL; + void ICapnpSerializable.Deserialize(DeserializerState arg_) + { + var reader = READER.create(arg_); + Result = reader.Result; + applyDefaults(); + } + + public void serialize(WRITER writer) + { + writer.Result = Result; + } + + void ICapnpSerializable.Serialize(SerializerState arg_) + { + serialize(arg_.Rewrap()); + } + + public void applyDefaults() + { + } + + public int Result + { + get; + set; + } + + public struct READER + { + readonly DeserializerState ctx; + public READER(DeserializerState ctx) + { + this.ctx = ctx; + } + + public static READER create(DeserializerState ctx) => new READER(ctx); + public static implicit operator DeserializerState(READER reader) => reader.ctx; + public static implicit operator READER(DeserializerState ctx) => new READER(ctx); + public int Result => ctx.ReadDataInt(0UL, 0); + } + + public class WRITER : SerializerState + { + public WRITER() + { + this.SetStruct(1, 0); + } + + public int Result + { + get => this.ReadDataInt(0UL, 0); + set => this.WriteData(0UL, value, 0); + } + } + } +} diff --git a/Capnp.Net.Runtime/SerializerState.cs b/Capnp.Net.Runtime/SerializerState.cs index 14c994d..37d0475 100644 --- a/Capnp.Net.Runtime/SerializerState.cs +++ b/Capnp.Net.Runtime/SerializerState.cs @@ -92,26 +92,38 @@ namespace Capnp ts = new TS(); - InvalidOperationException InvalidWrap() => - new InvalidOperationException("Incompatible cast"); - - switch (ts.Kind) + if (Kind != ObjectKind.Nil) { - case ObjectKind.Struct: - case ObjectKind.ListOfStructs: - if (ts.Kind != Kind || - ts.StructDataCount != StructDataCount || - ts.StructPtrCount != StructPtrCount) - throw InvalidWrap(); - break; + InvalidOperationException InvalidWrap() => + new InvalidOperationException("Incompatible cast"); - case ObjectKind.Nil: - break; + switch (ts.Kind) + { + case ObjectKind.Struct: + case ObjectKind.ListOfStructs: + if (ts.Kind != Kind || + ts.StructDataCount != StructDataCount || + ts.StructPtrCount != StructPtrCount) + throw InvalidWrap(); + break; - default: - if (ts.Kind != Kind) - throw InvalidWrap(); - break; + case ObjectKind.Nil: + break; + + default: + if (ts.Kind != Kind) + throw InvalidWrap(); + break; + } + + ts.SegmentIndex = SegmentIndex; + ts.Offset = Offset; + ts.ListElementCount = ListElementCount; + ts.StructDataCount = StructDataCount; + ts.StructPtrCount = StructPtrCount; + ts.Kind = Kind; + ts.CapabilityIndex = CapabilityIndex; + ts._linkedStates = _linkedStates; } if (Owner != null) @@ -119,15 +131,6 @@ namespace Capnp else ts.Bind(MsgBuilder); - ts.SegmentIndex = SegmentIndex; - ts.Offset = Offset; - ts.ListElementCount = ListElementCount; - ts.StructDataCount = StructDataCount; - ts.StructPtrCount = StructPtrCount; - ts.Kind = Kind; - ts.CapabilityIndex = CapabilityIndex; - ts._linkedStates = _linkedStates; - return ts; }