AqlaSolutions / AqlaSerializer

Binary serializer with full .NET support!
http://www.aqla.net
Other
17 stars 3 forks source link

DeflateStream is not supported? #36

Closed inethui closed 2 years ago

inethui commented 2 years ago

The following test fails with the error: System.NotSupportedException : This operation is not supported. This code works for Protobuf-net.

        [Fact]
        public void TestCompress()
        {
            using (DeflateStream dest = new DeflateStream(new MemoryStream(), CompressionMode.Compress))
            {
                Serializer.Serialize(dest, "Test");
            }
        }
AqlaSolutions commented 2 years ago

Stacktrace?

inethui commented 2 years ago

Stack Trace: 

DeflateStream.get_Position()
ProtoWriter.ctor(Stream dest, TypeModel model, SerializationContext context) line 886
TypeModel.Serialize(Stream dest, Object value, SerializationContext context) line 240
TypeModel.Serialize(Stream dest, Object value) line 227
Serializer.Serialize[T](Stream destination, T instance) line 135
UnitTest.TestCompress() line 170
AqlaSolutions commented 2 years ago

Yeah, it's expected that it's possible to get stream position, if it's not supported in DeflateStream than you can't use it directly. Though you can make a wrapper around DeflateStream which implements Position. It should just count written bytes.

inethui commented 2 years ago

But this code works for Protobuf-net. Is Aqla supposed to support whatever Protobuf-net provides? The following code works:

            using (DeflateStream dest = new DeflateStream(new MemoryStream(), CompressionMode.Compress))
            {
                ProtoBuf.Serializer.Serialize(dest, "Test");
            }
AqlaSolutions commented 2 years ago

Mostly it supports things from Protobuf-net, but not using Position property is a very implementation specific thing. Ok, I'll see if Position can be avoided. For now you can workaround it using a wrapper.

inethui commented 2 years ago

We've already had a serialization solution which is a mix of BinaryFormatter and ProtoBuf, each has its own issues. I'm trying to consolidate them into Aqla, but found these two issues. It would be very much appreciated if you can get them addressed.

AqlaSolutions commented 2 years ago

Can you provide an example with full cycle: serialization + deserialization using DeflateStream?

inethui commented 2 years ago

This is an example of how to serialize/deserialize into/from a DeflateStream:

        public void TestCompress()
        {
            byte[] bytes;
            using (MemoryStream stream = new MemoryStream())
            {
                using (DeflateStream dest = new DeflateStream(stream, CompressionMode.Compress))
                {
                    ProtoBuf.Serializer.Serialize(dest, "Test");
                }

                bytes = stream.ToArray();
            }

            using (var stream = new MemoryStream(bytes))
                using (DeflateStream dest = new DeflateStream(stream, CompressionMode.Decompress))
                {
                    var str = ProtoBuf.Serializer.Deserialize<string>(dest);
                    Assert.Equal("Test", str);
                }
        }
AqlaSolutions commented 2 years ago

Ok, I fixed it so that Position is not used unless it is really necessary. You can test it with the develop branch. But mind that some features require seeking during reading like If you try to reference an object from inside itself.

inethui commented 2 years ago

Thanks for the quick turn around. I want to make Aqla our standard serializer, but these two issues have caused many unit tests to fail. Now you have quickly fixed issue #36, it would be really helpful if you can also fix #35.

inethui commented 2 years ago

I got the following error while trying to run our tests with the Aqla develop branch: AqlaSerializer.ProtoAggregateException : One or multiple exceptions occurred: InvalidOperationException (Non-public member cannot be used with full dll compilation: Any idea what could be the cause?

AqlaSolutions commented 2 years ago

It means you are serializing a private field. If it's not the case can you give me a repro?

inethui commented 2 years ago

Yes, we are serializing private fields. We use reflection to find out all fields (public and private) and use RuntimeTypeModel APIs to register our classes and fields. This has never been a problem before.

inethui commented 2 years ago

I have encountered similar issues before. One thing I noticed is that if I download and use the binaries you built, then this problem goes away.

inethui commented 2 years ago

Can you please publish the binaries? I would like to give it a try.

inethui commented 2 years ago

What does "full dll compilation" mean?

AqlaSolutions commented 2 years ago

When you call RuntimeTypeModel.Compile(dllName) it generates dll that can serialize your classes without reflection. If works as any other compiled C# code so it can't access private members.

AqlaSolutions commented 2 years ago

It looks like you use DEBUG configuration of aqlaserializer project, that's why it attempts to test dll compilation. Just switch to release.

inethui commented 2 years ago

You are right, I was running in DEBUG configuration. However, I didn't call RuntimeTypeModel.Compile(dllName), instead what I called is RuntimeTypeModel.Default.CompileInPlace(). Does this have the same effect as "RuntimeTypeModel.Compile(dllName)"?

inethui commented 2 years ago

I'm having some trouble to build the release build of Aqla. Can you post the release build of it? Thanks

inethui commented 2 years ago

Never mind, I figured out how to create the release build. I've verified that this issue is fixed in develop branch. Now can you please create a nuget package? I will ask our IT to download it and put it in our internal nuget repo so that our system can start to use it.

AqlaSolutions commented 2 years ago

I've published the new release.