www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.bitmanip help - how to combine bitfields and read

reply kookman <thekookman gmail.com> writes:
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.
Mar 10 2020
parent kookman <thekookman gmail.com> writes:
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; } }
Mar 10 2020