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

Binghoo Dang dangbinghoo at gmail.com
Thu Dec 21 13:25:22 UTC 2017


hi Davis,

Thanks for your great help to me!

Yeah, the library may had a design principle when it was 
designed, as you can see the buffer appender is not that suitable 
for an application-defined structured data packing.

And after I turn to the bitfield, I then got another trouble:

The bitfield template only allows (8, 64) bits to be packed, so 
in a real application, and obviously, in my application, the 
packet is greater than 8 bytes.

So, the appender and bitfield are not practical for my situation. 
And now, I realized that the problem what I have done is only 
using bit-shift other than using direct cast operator.

In C, one can directly cast a struct to memory bytes, for D, the 
struct can have methods, and the alignment is also more complex. 
So, I think that handy packing and unpacking elements in a struct 
to D array is just OK. And better than C, the D array is 
autoincremented, this feature already makes the thing more 
simpler to understand.

So, before I can write my own template for generating the packing 
and unpacking code, I would just remove the bit shit.

Again, Thank you very much!


On Thursday, 21 December 2017 at 12:21:55 UTC, Jonathan M Davis 
wrote:
> 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