How to pack a struct to a ubyte[] in a more "The D way" style ?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Dec 21 12:21:55 UTC 2017


On Monday, December 18, 2017 08:45:32 Binghoo Dang via Digitalmars-d-learn 
wrote:
> hi Davis,
>
> I read the std.bitmanip, and I tried to test the code like below:
>
> ```
> import std.stdio;
> import std.array;
> import std.bitmanip;
> void main(string[] args)
> {
>      align(1) struct c {
>          ushort c1;
>          uint c2;
>          //ubyte[8] c3;
>      }
>      ubyte[] buffer;
>      auto ap = appender(&buffer);
>      uint a = 0x11223344;
>      ushort b = 0x6677;
>      ap.append!uint(a);
>      ap.append!ushort(b);
>
>      c cobj;
>      cobj.c1 = 0xEEFF;
>      cobj.c2 = 0xDEADBEAF;
>      //cobj.c3 = [0x12, 0x34, 0x56, 0x78];
>      ap.append(cobj);
>
>      ubyte[3] d = [0xAA, 0xBB, 0xCC];
>      ap.append(d);
>
>      foreach(e; buffer) {
>          writef("%02X ", e);
>      }
> }
> ```
> For compiling this code, I got error like this
>
> > onlineapp.d(22): Error: template std.bitmanip.append cannot
> > deduce function from >argument types !()(RefAppender!(ubyte[]),
> >
> > c), candidates are:
> >/dlang/dmd/linux/bin64/../../src/phobos/std/bitmanip.d(3623):
> >    std.bitmanip.append(T, Endian endianness = Endian.bigEndian,
> >
> >R)(R range, T value) >if (canSwapEndianness!T &&
> >isOutputRange!(R, ubyte))
> >onlineapp.d(25): Error: template std.bitmanip.append cannot
> >deduce function from >argument types !()(RefAppender!(ubyte[]),
> >ubyte[3]), candidates are:
> >
> >/dlang/dmd/linux/bin64/../../src/phobos/std/bitmanip.d(3623):
> >    std.bitmanip.append(T, Endian endianness = Endian.bigEndian,
> >
> >R)(R range, T value) >if (canSwapEndianness!T &&
> >isOutputRange!(R, ubyte))
>
> It seems that the appending is just allow using the fundamental
> types like uint, ushort, it does not support struct, and can't
> support dynamic array too. As the hardware protocol is a
> dynamic-length style, so I also need to support append array or
> another buffer directly.
>
> It seems that I can't get the point how to using the bitmanip to
> do the packing I need, and also I have no idea what the unpacking
> will look like.

write, append, peek, and read all operate on integral types only. If you
have an array of int or whatnot that you want to put into an array of ubyte,
then just use a loop, and if you have a struct, then write or append each of
the members individually. Those functions are for making it clean and easy
to write integral types to an array or range of ubyte (or to read them back
out again) while properly taking endianness into account, not for directly
serializing objects.

I really don't know what to tell you if the examples in the docs aren't
enough to figure out how to use the functions, because if I were trying to
show you how, I'd give very similar examples, and I don't know why the docs
wouldn't be clear as they are or how they could be made clearer for you.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list