std.bitmanip help - how to combine bitfields and read

kookman thekookman at gmail.com
Wed Mar 11 06:02:49 UTC 2020


On Wednesday, 11 March 2020 at 05:25:43 UTC, kookman wrote:
> I am using libpcap to read from stored pcap files, and want to 
> use std.bitmanip.bitfields to read TCP flags from the file, 
> using a struct like:
>
> struct TcpHeader {
>     align(1):
>     ushort srcPort;
>     ushort dstPort;
>     uint seqNo;
>     uint ackNo;
>     mixin(bitfields!(
>         bool, "flagFin", 1,
>         bool, "flagSyn", 1,
>         bool, "flagRst", 1,
>         bool, "flagPsh", 1,
>         bool, "flagAck", 1,
>         bool, "flagUrg", 1,
>         bool, "flagEce", 1,
>         bool, "flagCwr", 1,
>         bool, "flagNs",  1,
>         ubyte, "reserved", 3,
>         ubyte, "dataOffsetWords", 4   // in 32bit words, min=5, 
> max=15
>     ));
>     ushort windowSize;
>     ushort checksum;
>     ushort urgentPtr;
>
>     this(inout ubyte[] bytes)
>     {
>         srcPort = bytes.read!ushort();
>         dstPort = bytes.read!ushort();
>         seqNo = bytes.read!uint();
>         ackNo = bytes.read!uint();
>         // now what? how to read bitfields??
>     }
>
>     const uint dataOffset()        // convenience method to get 
> offset in bytes
>     {
>         return dataOffsetWords * 4;
>     }
> }
>
> How can I get at the private field behind the bitfields to read 
> into it. I'm using std.bitmanip.read because I need the network 
> order (bigendian) conversion for this data.

Actually, doing it a "smarter" way worked:

struct TcpHeader {
     align(1):
     ushort srcPort;
     ushort dstPort;
     uint seqNo;
     uint ackNo;
     mixin(bitfields!(
         bool, "flagFin", 1,
         bool, "flagSyn", 1,
         bool, "flagRst", 1,
         bool, "flagPsh", 1,
         bool, "flagAck", 1,
         bool, "flagUrg", 1,
         bool, "flagEce", 1,
         bool, "flagCwr", 1,
         bool, "flagNs",  1,
         ubyte, "reserved", 3,
         ubyte, "dataOffsetWords", 4   // in 32bit words, min=5, 
max=15
     ));
     ushort windowSize;
     ushort checksum;
     ushort urgentPtr;

     this(inout(ubyte)[] bytes)
     {
         import std.traits: FieldNameTuple;
         static foreach (f; FieldNameTuple!TcpHeader) {
             pragma(msg, f);
             __traits(getMember, this, f) = 
bytes.read!(typeof(__traits(getMember, this, f)));
         }
     }

     const uint dataOffset()        // convenience method to get 
offset in bytes
     {
         return dataOffsetWords * 4;
     }
}


More information about the Digitalmars-d-learn mailing list