1 /**
2  * Standalone encoding/decoding functions
3  */
4 module bformat.marshall;
5 
6 import niknaks.bits : toBytes, bytesToIntegral, order, Order;
7 
8 /** 
9  * Decodes the provided bformat message into the
10  * message itself
11  *
12  * Params:
13  *   bformatBytes = the bformat payload the decode
14  * Returns: the decoded message
15  */
16 public byte[] decodeMessage(byte[] bformatBytes)
17 {
18 	/* Construct a buffer to receive into */
19 	byte[] receiveBuffer;
20 
21 	/* Get the length of the message */
22 	byte[4] messageLengthBytes = bformatBytes[0..4];
23 
24 	/* Response message length */
25 	uint messageLength;
26 
27 	/* Order the bytes into Little endian (only flips if host order doesn't match LE) */
28 	messageLength = order(bytesToIntegral!(uint)(cast(ubyte[])messageLengthBytes), Order.LE);
29 
30 
31 	/* Read the full message */
32 	receiveBuffer = bformatBytes[4..4+messageLength];
33 
34 	return receiveBuffer;
35 }
36 
37 /** 
38  * Encodes the provided message into the bformat format
39  *
40  * Params:
41  *   message = the buffer containing bytes to encode
42  * Returns: the encoded payload
43  */
44 public byte[] encodeBformat(byte[] message)
45 {
46 	/* The message buffer */
47 	byte[] messageBuffer;
48 
49 	/* Encode the 4 byte message length header (little endian) */
50 	messageBuffer ~= cast(byte[])toBytes(order(cast(int)message.length, Order.LE));
51 
52 	/* Add the message to the buffer */
53 	messageBuffer ~= cast(byte[])message;
54 
55 	return messageBuffer;
56 }
57 
58 version(unittest)
59 {
60     import std.string : cmp;
61 }
62 
63 unittest
64 {
65     string message = "This is my message";
66     byte[] bformatEncoded = encodeBformat(cast(byte[])message);
67 
68     byte[] decodedMessageBytes = decodeMessage(bformatEncoded);
69     string decodedMessage = cast(string)decodedMessageBytes;
70 
71     assert(cmp(message, decodedMessage) == 0);
72 }