jefffhaynes / BinarySerializer

A declarative serialization framework for controlling formatting of data at the byte and bit level using field bindings, converters, and code.
MIT License
289 stars 62 forks source link

Handling length information #151

Closed jonasdroste closed 4 years ago

jonasdroste commented 4 years ago

I have to handle a binary protocol that's modelled by the provided class structure. Currently I'm wondering how to handle the length information as I need to do calculations depending which subtype is used. Furthermore I'm wondering how to calculate the size of the whole Payload field an feed that into PayloadLength

    public class Packet
    {
        [FieldOrder(0)]
        public byte ProtocolVersion { get; set; }

        [FieldOrder(1)]
        public byte InvProtocolVersion { get; set; }

        [FieldOrder(2)]
        public dPayloadType PayloadType { get; set; }

        [FieldOrder(4)]
        [Subtype(nameof(PayloadType), dPayloadType.GenericNACK, typeof(GenericNACKPayload))]
        [Subtype(nameof(PayloadType), dPayloadType.Request, typeof(Request))]
        [Subtype(nameof(PayloadType), dPayloadType.UserData, typeof(UserData))]
        public dPayload Payload { get; set; }        
    }
    public class dPayload
    {
        [FieldOrder(0)]
        public UInt32 PayloadLength { get; set; }
    }
    public class GenericNACKPayload : dPayload
    {
        [FieldOrder(0)]
        [FieldLength(1)]
        public byte NackCode { get; set; }
    }

    public class Request : dPayload
    {
        [FieldOrder(0)]
        public byte[] EID { get; set; } // Size is equal to PayloadLength 
    }

    public class UserData : dPayload
    {
        [FieldOrder(0)]
        public byte SA { get; set; }
        [FieldOrder(1)]
        public byte TA { get; set; }
        [FieldOrder(2)]
        public byte[] UD { get; set; } // Size is equal to PayloadLength - 2
    }
jefffhaynes commented 4 years ago

I’m only looking at it on my phone at the moment so it’s hard to say but I think if you simply inject a “payload container” object you can limit the length of the payload object and it should all come out in the wash.

On Thu, Mar 19, 2020 at 3:59 AM Jonas Droste notifications@github.com wrote:

I have to handle a binary protocol that's modelled by the provided class structure. Currently I'm wondering how to handle the length information as I need to do calculations depending which subtype is used. Furthermore I'm wondering how to calculate the size of the whole Payload field an feed that into PayloadLength

public class Packet
{
    [FieldOrder(0)]
    public byte ProtocolVersion { get; set; }

    [FieldOrder(1)]
    public byte InvProtocolVersion { get; set; }

    [FieldOrder(2)]
    public dPayloadType PayloadType { get; set; }

    [FieldOrder(4)]
    [Subtype(nameof(PayloadType), dPayloadType.GenericNACK, typeof(GenericNACKPayload))]
    [Subtype(nameof(PayloadType), dPayloadType.Request, typeof(Request))]
    [Subtype(nameof(PayloadType), dPayloadType.UserData, typeof(UserData))]
    public dPayload Payload { get; set; }
}
public class dPayload
{
    [FieldOrder(0)]
    public UInt32 PayloadLength { get; set; }
}
public class GenericNACKPayload : dPayload
{
    [FieldOrder(0)]
    [FieldLength(1)]
    public byte NackCode { get; set; }
}

public class Request : dPayload
{
    [FieldOrder(0)]
    public byte[] EID { get; set; } // Size is equal to PayloadLength
}

public class UserData : dPayload
{
    [FieldOrder(0)]
    public byte SA { get; set; }
    [FieldOrder(1)]
    public byte TA { get; set; }
    [FieldOrder(2)]
    public byte[] UD { get; set; } // Size is equal to PayloadLength - 2
}

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jefffhaynes/BinarySerializer/issues/151, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACKIUR2EH4EUPQG3DFDQC3TRIHGGPANCNFSM4LPCZFRA .

-- If you want to build a ship, don't drum up people together to collect wood and don't assign them tasks and work, but rather teach them to long for the endless immensity of the sea.

Antoine de Saint-Exupery

jefffhaynes commented 4 years ago

Looking at it now you don't even need to add anything, just move your length definition to the packet like this:

public class Packet
{
    [FieldOrder(0)]
    public byte ProtocolVersion { get; set; }

    [FieldOrder(1)]
    public byte InvProtocolVersion { get; set; }

    [FieldOrder(2)]
    public dPayloadType PayloadType { get; set; }

    [FieldOrder(3)]
    public UInt32 PayloadLength { get; set; }

    [FieldOrder(4)]
    [FieldLength(nameof(PayloadLength))]
    [Subtype(nameof(PayloadType), dPayloadType.GenericNACK, typeof(GenericNACKPayload))]
    [Subtype(nameof(PayloadType), dPayloadType.Request, typeof(Request))]
    [Subtype(nameof(PayloadType), dPayloadType.UserData, typeof(UserData))]
    public dPayload Payload { get; set; }
}

public abstract class dPayload
{
}

If I'm not mistaken, this should match the format you're trying to achieve.

jefffhaynes commented 4 years ago

Closing this. Please reopen if I'm missing something or you need more help with this.