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


Reply via email to