Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing and deserializing a bit field

I've been handed a document that defines a set of messages that are transmitted and received over a serial communications channel. I'd like to take the incoming messages and deserialize them into objects, and serialize my outbound messages as well. The encoding over the wire is established and not changeable, and consists of various bitfields in the header and varying payloads, e.g.,

class Message{
int msg_num : 7
int dest_addr : 4
bool SRR : 1
bool IDE : 1
int source_addr : 6
//... and so on...
}

I took a look at using protobufs, but it appears that their varint method of encoding is established. I've also looked at boost-serialization, but based on what I've read so far, how the encoding is done there is not entirely clear.

So, a few questions:

  • Can I use boost-serialization to convert my bytestream to objects?
  • With a goal of not having to roll my own routines for serialization (a maintenance mess), is there a preferred mechanism for accomplishing my task (e.g., a custom boost-serialization Archive, another method I've not discovered)
like image 346
jdt141 Avatar asked Feb 08 '12 22:02

jdt141


1 Answers

I think you won't find an easy-to-use serializer that will match the custom protocol you are looking at. But it look the set of primitives you have (int, bool + size ) are simple enough to be able to write your own decoder/encoder. Simply generating C/C++ code based on the message received. It should be fairly simple task to generate a compilable code taking such description. It should be an automated generation done at the compile time - similar to what protobuf/Corba are doing.

Example: from the specification:

class Message{
    int msg_num : 7
    int dest_addr : 4
    bool SRR : 1
    bool IDE : 1
    int source_addr : 6
    //... and so on...
}

the converter could write a function with body similar to (abstract notation and assuming MSB):

Decoder:

m = new Message()
{
    long long val = 0
    for(int i=0; i<7; i++) {
        val <<= 8
        val += nextByte()    
    }
    m.msg_num = val
}
{
    long long val = 0
    for(int i=0; i<4; i++) {
        val <<= 8
        val += nextByte()    
    }
    m.dest_addr = val
}
{
    int val = nextByte()
    m.SRR = val
}
{
    int val = nextByte()
    m.IDE = val
}
{
    long long val = 0
    for(int i=0; i<6; i++) {
        val <<= 8
        val += nextByte()    
    }
    m.source_addr = val
}
// and so on

Encoder:

{
    long long val = m.msg_num
    for(int i=0;i<7;i++) {
        writeByte(val & 0xFF)
        val >>= 8
    }
}
{
    long long val = m.dest_addr
    for(int i=0;i<4;i++) {
        writeByte(val & 0xFF)
        val >>= 8
    }
}
....

That should be pretty easy to generate and the simplest way to make sure the encoding is custom.

like image 114
Jarek Potiuk Avatar answered Oct 31 '22 22:10

Jarek Potiuk