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

Binghoo Dang dangbinghoo at gmail.com
Mon Dec 18 03:00:47 UTC 2017


hi,

I'm a dlang newbie, and I recently made a program that interacts 
with an RFID Reader, it's basically a Serial-Port communication 
model. And after 2 days, I finally got a working code like these:

```
     enum RCPCmd{
         RCPCMD_GET_REGION = 0x06,
         RCPCMD_SET_REGION = 0x07,
         RCPCMD_SYS_RESET = 0x08,
         ...........

         RCPCMD_START_AUTOREAD2 = 0x36,
         RCPCMD_STOP_AUTOREAD2 = 0x37,

         RCPCMD_WRITE_TYPEC_TAGDATA = 0x46,

         RCPCMD_FAIL = 0xFF
     }

     enum {
         RCPMSG_CMD = 0x00,
         RCPMSG_RESP = 0x01,
         RCPMSG_NOTIFY = 0x02
     }

     private struct RCProtocol
     {
         enum {
             RCPPKT_PRE = 0xBB,
             RCPPKT_END = 0x7E
         }

         align(1) struct RCPacketHdr {
             ubyte msgtype;
             ubyte cmdcode;
             ushort len;
         }

         /**
          * These kind of members will be need only for private 
var for making a cmd packet.
          * But access-able as a parsed result for a incomming 
packet.
          */
         ubyte preamble;
         RCPacketHdr hdr;
         ubyte[] payload; //ubyte[len] of payload.
         ubyte end;
         ushort crc16;

         ubyte[] makeCMDPacket(RCPCmd cmd, in ubyte[] data)
         {
             this.preamble = RCPPKT_PRE;
             this.hdr.msgtype = RCPMSG_CMD;
             this.hdr.cmdcode =  cast (ubyte) cmd;
             this.hdr.len = 0xffff & data.length;
             this.end = RCPPKT_END;
             this.payload = data.dup;

             ubyte [] pkt;
             pkt ~= this.hdr.msgtype;
             pkt ~= this.hdr.cmdcode;
             pkt ~= this.hdr.len >> 8;
             pkt ~= this.hdr.len & 0xff;
             pkt = this.preamble ~ pkt ~ this.payload ~ this.end;

             // calc crc16 for Preamble + HDR + Data + END
             this.crc16 = new RCPCRC16().calc(pkt);

             pkt ~= this.crc16 >> 8;
             pkt ~= this.crc16 & 0xff;

             return pkt;
         }

         int parseRespPacket(in ubyte[] recv)
         {
             const size_t len = recv.length;
             if (recv is null)
                 return PARSE_ERR;

             if (len < 8)
                 return PARSE_ERR_PKTLEN;

             if (recv[0] !is RCPPKT_PRE)
                 return PARSE_ERR_PKTHEAD;

             this.preamble = recv[0];
             this.hdr.msgtype = recv[1];
             this.hdr.cmdcode = recv[2];
             this.hdr.len = (recv[3] << 8) + 0xff & recv[4];

             if ( this.hdr.len > (len - 8))
                 return PARSE_ERR_PKT;

             this.end = recv[5+this.hdr.len];

             if (this.end != RCPPKT_END)
                 return PARSE_ERR_PKT;

             this.payload = recv[5 .. (5+this.hdr.len)].dup;

             ubyte [] pkt;
             pkt ~= this.hdr.msgtype;
             pkt ~= this.hdr.cmdcode;
             pkt ~= this.hdr.len >> 8;
             pkt ~= this.hdr.len & 0xff;
             pkt = this.preamble ~ pkt ~ this.payload ~ this.end;

             // calc crc16 for Preamble + HDR + Data + END
             const ushort desired_crc = new RCPCRC16().calc(pkt);

             this.crc16 = (recv[6+this.hdr.len] << 8) + 
recv[7+this.hdr.len];
             if (this.crc16 != desired_crc) {
                 writefln("-- PARSE ERR: CRC, desired = %04X, 
actuall is %04X", this.crc16, desired_crc);
                 return PARSE_ERR_CRC;
             }

             return PARSE_OK;
         }
     }

```

It's basically a C-style code, and it works perfect, But I know 
that this is not a "D-way", So, any suggestions?

Thanks!


More information about the Digitalmars-d-learn mailing list