How do I deserialize a binary AMQP message received with protobuf-net?

518 views Asked by At

I am just learning C# and am using it with Godot. We are trying to send a binary Protobuf-encoded message from a client over AMQP and receive it with the C# script running in Godot.

I am at the point where the message is received and I am trying to deserialize it. The message body is a 44-byte array, but the protobuf-net deserialize doesn't take a byte array. The message body is of type object but it definitely contains a byte array.

    byte[] binaryBody = (byte[])message.Body;
    CommandBuffer commandBuffer;
    commandBuffer = Serializer.Deserialize<CommandBuffer>(binaryBody);

This results in an error:

The call is ambiguous between the following methods or properties: 'Serializer.Deserialize<T>(ReadOnlyMemory<byte>, T, object)' and 'Serializer.Deserialize<T>(ReadOnlySpan<byte>, T, object)' [srt-godot-test]csharp(CS0121)

Trying to convert binaryBody to a MemoryStream results in all kind of a mess and a protobuf that cannot be properly decoded:

    MemoryStream st = new MemoryStream();
    st.Write(binaryBody, 0, binaryBody.Length);

It seems like I should just be able to deserialize binaryBody somehow, but I cannot figure out what to do here.

1

There are 1 answers

0
Erik Jacobs On

I found this post: Protobuf-net Serialize/Deserialize to/from byte arrays

Which lead me to the MemoryStream page: https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream.-ctor?redirectedfrom=MSDN&view=net-6.0#System_IO_MemoryStream__ctor_System_Byte___

And I noticed this option: https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream.-ctor?view=net-6.0#system-io-memorystream-ctor(system-byte()-system-boolean)

Which resulted in this code:

  void GameEventReceived(IReceiverLink receiver, Message message)
  {
    GD.Print("Event received!");
    // accept the message so that it gets removed from the queue
    receiver.Accept(message);

    byte[] binaryBody = (byte[])message.Body;

    MemoryStream st = new MemoryStream(binaryBody, false);

    // prep a command buffer for processing the message
    CommandBuffer commandBuffer;
    commandBuffer = Serializer.Deserialize<CommandBuffer>(st);
  }

The key was creating the MemoryStream directly from the bytestring.