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;
}