Protocol conformity and serialization tests for UUIDs
diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas
index 8ee8a35..c354a37 100644
--- a/lib/delphi/src/Thrift.Serializer.pas
+++ b/lib/delphi/src/Thrift.Serializer.pas
@@ -66,7 +66,7 @@
   public
     constructor Create( const aProtFact  : IProtocolFactory = nil;    // defaults to TBinaryProtocol
                         const aTransFact : ITransportFactory = nil;
-                        const aConfig   : IThriftConfiguration = nil);
+                        const aConfig    : IThriftConfiguration = nil);
 
     // DTOR
     destructor Destroy;  override;
@@ -74,6 +74,11 @@
     // Deserialize the Thrift object data.
     procedure Deserialize( const input : TBytes; const target : IBase);  overload;
     procedure Deserialize( const input : TStream; const target : IBase);  overload;
+
+    // helper
+    property  Protocol  : IProtocol read FProtocol;
+    property  Transport : ITransport read FTransport;
+    property  Stream    : TThriftMemoryStream read FStream;
   end;
 
 
@@ -164,14 +169,14 @@
 
 constructor TDeserializer.Create( const aProtFact  : IProtocolFactory;
                                   const aTransFact : ITransportFactory;
-                                  const aConfig   : IThriftConfiguration);
+                                  const aConfig    : IThriftConfiguration);
 var adapter : IThriftStream;
     protfact : IProtocolFactory;
 begin
   inherited Create;
 
-  FStream    := TThriftMemoryStream.Create;
-  adapter    := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
+  FStream := TThriftMemoryStream.Create;
+  adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
 
   FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig);
   if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport);
@@ -205,8 +210,11 @@
   try
     iBytes := Length(input);
     FStream.Size := iBytes;
-    if iBytes > 0
-    then Move( input[0], FStream.Memory^, iBytes);
+    if iBytes > 0 then begin
+      Move( input[0], FStream.Memory^, iBytes);
+      Transport.ResetMessageSizeAndConsumedBytes();  // size has changed
+      Transport.UpdateKnownMessageSize(iBytes);
+    end;
 
     target.Read( FProtocol);
   finally
@@ -221,9 +229,15 @@
 var before : Int64;
 begin
   try
-    before := FStream.Position;
-    FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
-    FStream.Position := before;
+    if Assigned(input) then begin
+      before := FStream.Position;
+      ASSERT( before = 0);
+      FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
+      FStream.Position := before;
+      Transport.ResetMessageSizeAndConsumedBytes();  // size has changed
+      Transport.UpdateKnownMessageSize(FStream.Size);
+    end;
+
     target.Read( FProtocol);
   finally
     FStream.Size := 0;  // free any allocated memory
diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas
index 466fb26..7f5b829 100644
--- a/lib/delphi/test/serializer/TestSerializer.Tests.pas
+++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas
@@ -49,7 +49,7 @@
 
 type
   TFactoryPair = record
-    prot : IProtocolFactory;
+    proto : IProtocolFactory;
     trans : ITransportFactory;
   end;
 
@@ -72,8 +72,9 @@
     class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair);  overload;
     class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair);  overload;
 
-    class procedure ValidateReadToEnd( const input : TBytes; const serial : TDeserializer);  overload;
-    class procedure ValidateReadToEnd( const input : TStream; const serial : TDeserializer);  overload;
+    class procedure Deserialize( const input : TBytes; out target : TGuid; const factory : TFactoryPair);  overload;
+
+    class procedure ValidateReadToEnd( const serial : TDeserializer);  overload;
 
     class function LengthOf( const bytes : TBytes) : Integer; overload; inline;
     class function LengthOf( const bytes : IThriftBytes) : Integer; overload; inline;
@@ -90,6 +91,9 @@
     procedure Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
     procedure Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
 
+    procedure Test_ProtocolConformity( const factory : TFactoryPair; const stream : TFileStream);
+    procedure Test_UuidDeserialization( const factory : TFactoryPair; const stream : TFileStream);
+
   public
     constructor Create;
     destructor Destroy;  override;
@@ -143,7 +147,7 @@
 procedure TTestSerializer.AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory);
 var rec : TFactoryPair;
 begin
-  rec.prot  := aProto;
+  rec.proto := aProto;
   rec.trans := aTrans;
   FProtocols.Add( rec);
 end;
@@ -177,6 +181,53 @@
 end;
 
 
+procedure TTestSerializer.Test_ProtocolConformity( const factory : TFactoryPair; const stream : TFileStream);
+begin
+  Test_UuidDeserialization( factory, stream);
+  // add more tests here
+end;
+
+
+procedure TTestSerializer.Test_UuidDeserialization( const factory : TFactoryPair; const stream : TFileStream);
+
+  function CreateGuidBytes : TBytes;
+  var obj : TObject;
+      i : Integer;
+  begin
+    obj := factory.proto as TObject;
+
+    if obj is TJSONProtocolImpl.TFactory then begin
+      result := TEncoding.UTF8.GetBytes('"00112233-4455-6677-8899-aabbccddeeff"');
+      Exit;
+    end;
+
+    if (obj is TBinaryProtocolImpl.TFactory)
+    or (obj is TCompactProtocolImpl.TFactory)
+    then begin
+      SetLength(result,16);
+      for i := 0 to Length(result)-1 do result[i] := (i * $10) + i;
+      Exit;
+    end;
+
+    raise Exception.Create('Unhandled case');
+  end;
+
+
+var tested, correct : TGuid;
+    bytes   : TBytes;
+begin
+  // write
+  bytes := CreateGuidBytes();
+
+  // init + read
+  Deserialize( bytes, tested, factory);
+
+  // check
+  correct := TGuid.Create('{00112233-4455-6677-8899-aabbccddeeff}');
+  ASSERT( tested = correct);
+end;
+
+
 procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
 var tested, correct : IOneOfEach;
     bytes   : TBytes;
@@ -385,6 +436,11 @@
       for factory in FProtocols do begin
         Writeln('- '+UserFriendlyName(factory));
 
+        // protocol conformity tests
+        if (method = TMethod.mt_Bytes) and (factory.trans = nil)
+        then Test_ProtocolConformity( factory, stream);
+
+        // normal objects
         Test_OneOfEach(       method, factory, stream);
         Test_CompactStruct(   method, factory, stream);
         Test_ExceptionStruct( method, factory, stream);
@@ -402,7 +458,7 @@
 
 class function TTestSerializer.UserFriendlyName( const factory : TFactoryPair) : string;
 begin
-  result := Copy( (factory.prot as TObject).ClassName, 2, MAXINT);
+  result := Copy( (factory.proto as TObject).ClassName, 2, MAXINT);
 
   if factory.trans <> nil
   then result := Copy( (factory.trans as TObject).ClassName, 2, MAXINT) +' '+ result;
@@ -472,7 +528,7 @@
   config := TThriftConfigurationImpl.Create;
   //config.MaxMessageSize := 0;   // we don't read anything here
 
-  serial := TSerializer.Create( factory.prot, factory.trans, config);
+  serial := TSerializer.Create( factory.proto, factory.trans, config);
   try
     result := serial.Serialize( input);
   finally
@@ -488,7 +544,7 @@
   config := TThriftConfigurationImpl.Create;
   //config.MaxMessageSize := 0;   // we don't read anything here
 
-  serial := TSerializer.Create( factory.prot, factory.trans, config);
+  serial := TSerializer.Create( factory.proto, factory.trans, config);
   try
     serial.Serialize( input, aStream);
   finally
@@ -504,10 +560,10 @@
   config := TThriftConfigurationImpl.Create;
   config.MaxMessageSize := Length(input);
 
-  serial := TDeserializer.Create( factory.prot, factory.trans, config);
+  serial := TDeserializer.Create( factory.proto, factory.trans, config);
   try
     serial.Deserialize( input, target);
-    ValidateReadToEnd( input, serial);
+    ValidateReadToEnd( serial);
   finally
     serial.Free;
   end;
@@ -521,44 +577,49 @@
   config := TThriftConfigurationImpl.Create;
   config.MaxMessageSize := input.Size;
 
-  serial := TDeserializer.Create( factory.prot, factory.trans, config);
+  serial := TDeserializer.Create( factory.proto, factory.trans, config);
   try
     serial.Deserialize( input, target);
-    ValidateReadToEnd( input, serial);
+    ValidateReadToEnd( serial);
   finally
     serial.Free;
   end;
 end;
 
 
-class procedure TTestSerializer.ValidateReadToEnd( const input : TBytes; const serial : TDeserializer);
+class procedure TTestSerializer.Deserialize( const input : TBytes; out target : TGuid; const factory : TFactoryPair);
+var serial : TDeserializer;
+    config : IThriftConfiguration;
+begin
+  config := TThriftConfigurationImpl.Create;
+  config.MaxMessageSize := Length(input);
+
+  serial := TDeserializer.Create( factory.proto, factory.trans, config);
+  try
+    serial.Stream.Write(input[0], Length(input));
+    serial.Stream.Position := 0;
+    serial.Transport.ResetMessageSizeAndConsumedBytes();  // size has changed
+
+    target := serial.Protocol.ReadUuid;
+  finally
+    serial.Free;
+  end;
+end;
+
+
+class procedure TTestSerializer.ValidateReadToEnd( const serial : TDeserializer);
 // we should not have any more byte to read
 var dummy : IBase;
 begin
   try
     dummy := TOneOfEachImpl.Create;
-    serial.Deserialize( input, dummy);
+    serial.Deserialize( nil, dummy);
     raise EInOutError.Create('Expected exception not thrown?');
   except
-    on e:TTransportExceptionEndOfFile do {expected};
+    on e:TTransportException do {expected};
     on e:Exception do raise; // unexpected
   end;
 end;
 
 
-class procedure TTestSerializer.ValidateReadToEnd( const input : TStream; const serial : TDeserializer);
-// we should not have any more byte to read
-var dummy : IBase;
-begin
-  try
-    input.Position := 0;
-    dummy := TOneOfEachImpl.Create;
-    serial.Deserialize( input, dummy);
-    raise EInOutError.Create('Expected exception not thrown?');
-  except
-    on e:TTransportExceptionEndOfFile do {expected};
-    on e:Exception do raise; // unexpected
-  end;
-end;
-
 end.
diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolConformityTests.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolConformityTests.cs
new file mode 100644
index 0000000..8c5988f
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolConformityTests.cs
@@ -0,0 +1,90 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using KellermanSoftware.CompareNetObjects;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Protocol;
+using Thrift.Protocol.Entities;
+using Thrift.Transport;
+using Thrift.Transport.Client;
+
+namespace Thrift.IntegrationTests.Protocols
+{
+    [TestClass]
+    public class ProtocolConformityTests : TestBase
+    {
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task ReadUuidFromStream(Type protocolType)
+        {
+            var expected = new Guid("{00112233-4455-6677-8899-aabbccddeeff}");
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using var stream = tuple.Stream;
+
+                await GenerateGuidTestData(stream, protocolType, default);
+                stream.Seek(0, SeekOrigin.Begin);
+                tuple.Transport.ResetMessageSizeAndConsumedBytes();  // length has changed
+
+                var actual = await tuple.Protocol.ReadUuidAsync(default);
+
+                var result = _compareLogic.Compare(expected, actual);
+                Assert.IsTrue(result.AreEqual, result.DifferencesString);
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        private static async Task GenerateGuidTestData(Stream stream, Type protocolType, CancellationToken cancel)
+        {
+            stream.Seek(0, SeekOrigin.Begin);
+
+            if(protocolType == typeof(TJsonProtocol))
+            {
+                await stream.WriteAsync(Encoding.UTF8.GetBytes("\"00112233-4455-6677-8899-aabbccddeeff\""), cancel);
+                return;
+            }
+
+            if (protocolType == typeof(TBinaryProtocol))
+            {
+                var data = new byte[16] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+                await stream.WriteAsync(data, cancel);
+                return;
+            }
+
+            if (protocolType == typeof(TCompactProtocol))
+            {
+                var data = new byte[16] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+                await stream.WriteAsync(data, cancel);
+                return;
+            }
+
+            throw new Exception($"Unhandled protocol: {protocolType.FullName}");
+        }
+    }
+}
diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
index f9f3117..844bd10 100644
--- a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
+++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
@@ -31,11 +31,8 @@
 namespace Thrift.IntegrationTests.Protocols
 {
     [TestClass]
-    public class ProtocolsOperationsTests
+    public class ProtocolsOperationsTests : TestBase
     {
-        private readonly CompareLogic _compareLogic = new();
-        private static readonly TConfiguration Configuration = new();
-
         [DataTestMethod]
         [DataRow(typeof(TBinaryProtocol), TMessageType.Call)]
         [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)]
@@ -99,7 +96,7 @@
                     await protocol.WriteStructEndAsync(default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadStructBeginAsync(default);
                     await protocol.ReadStructEndAsync(default);
@@ -135,7 +132,7 @@
                     await protocol.WriteFieldEndAsync(default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadFieldBeginAsync(default);
                     await protocol.ReadFieldEndAsync(default);
@@ -169,7 +166,7 @@
                     await protocol.WriteMapEndAsync(default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadMapBeginAsync(default);
                     await protocol.ReadMapEndAsync(default);
@@ -204,7 +201,7 @@
                     await protocol.WriteListEndAsync(default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadListBeginAsync(default);
                     await protocol.ReadListEndAsync(default);
@@ -238,7 +235,7 @@
                     await protocol.WriteSetEndAsync(default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadSetBeginAsync(default);
                     await protocol.ReadSetEndAsync(default);
@@ -271,7 +268,7 @@
                     await protocol.WriteBoolAsync(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadBoolAsync(default);
 
@@ -303,7 +300,7 @@
                     await protocol.WriteByteAsync(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadByteAsync(default);
 
@@ -335,7 +332,7 @@
                     await protocol.WriteI16Async(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadI16Async(default);
 
@@ -367,7 +364,7 @@
                     await protocol.WriteI32Async(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadI32Async(default);
 
@@ -399,7 +396,7 @@
                     await protocol.WriteI64Async(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadI64Async(default);
 
@@ -431,7 +428,7 @@
                     await protocol.WriteDoubleAsync(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadDoubleAsync(default);
 
@@ -449,6 +446,38 @@
         [DataRow(typeof(TBinaryProtocol))]
         [DataRow(typeof(TCompactProtocol))]
         [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadUuid_Test(Type protocolType)
+        {
+            var expected = new Guid("{00112233-4455-6677-8899-aabbccddeeff}");
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Stream)
+                {
+                    var protocol = tuple.Protocol;
+
+                    await protocol.WriteUuidAsync(expected, default);
+                    await tuple.Transport.FlushAsync(default);
+
+                    stream.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadUuidAsync(default);
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
         public async Task WriteReadString_Test(Type protocolType)
         {
             var expected = nameof(String);
@@ -463,7 +492,7 @@
                     await protocol.WriteStringAsync(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadStringAsync(default);
 
@@ -495,7 +524,7 @@
                     await protocol.WriteBinaryAsync(expected, default);
                     await tuple.Transport.FlushAsync(default);
 
-                    stream?.Seek(0, SeekOrigin.Begin);
+                    stream.Seek(0, SeekOrigin.Begin);
 
                     var actual = await protocol.ReadBinaryAsync(default);
 
@@ -508,16 +537,5 @@
                 throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
             }
         }
-
-        private record struct ProtocolTransportStack(Stream Stream, TTransport Transport, TProtocol Protocol);
-
-        private static ProtocolTransportStack GetProtocolInstance(Type protocolType)
-        {
-            var memoryStream = new MemoryStream();
-            var streamClientTransport = new TStreamTransport(memoryStream, memoryStream,Configuration);
-            if( Activator.CreateInstance(protocolType, streamClientTransport) is TProtocol protocol)
-                return new ProtocolTransportStack(memoryStream, streamClientTransport, protocol);
-            throw new Exception("Unexpected");
-        }
     }
 }
diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/TestBase.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/TestBase.cs
new file mode 100644
index 0000000..5cbdea9
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/TestBase.cs
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using KellermanSoftware.CompareNetObjects;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Thrift.Protocol;
+using Thrift.Transport;
+using Thrift.Transport.Client;
+
+namespace Thrift.IntegrationTests.Protocols
+{
+    public class TestBase
+    {
+        protected readonly CompareLogic _compareLogic = new();
+        protected static readonly TConfiguration Configuration = new();
+
+
+        protected record struct ProtocolTransportStack(Stream Stream, TTransport Transport, TProtocol Protocol);
+
+        protected static ProtocolTransportStack GetProtocolInstance(Type protocolType)
+        {
+            var memoryStream = new MemoryStream();
+            var streamClientTransport = new TStreamTransport(memoryStream, memoryStream, Configuration);
+            if (Activator.CreateInstance(protocolType, streamClientTransport) is TProtocol protocol)
+                return new ProtocolTransportStack(memoryStream, streamClientTransport, protocol);
+            throw new Exception("Unexpected");
+        }
+    }
+}