1 /** 2 * Standalone encoding/decoding functions 3 */ 4 module bformat.marshall; 5 6 /** 7 * Decodes the provided bformat message into the 8 * message itself 9 * 10 * Params: 11 * bformatBytes = the bformat payload the decode 12 * Returns: the decoded message 13 */ 14 public byte[] decodeMessage(byte[] bformatBytes) 15 { 16 /* Construct a buffer to receive into */ 17 byte[] receiveBuffer; 18 19 /* Get the length of the message */ 20 byte[4] messageLengthBytes = bformatBytes[0..4]; 21 22 /* Response message length */ 23 uint messageLength; 24 25 /* Little endian version you simply read if off the bone (it's already in the correct order) */ 26 version(LittleEndian) 27 { 28 messageLength = *cast(int*)messageLengthBytes.ptr; 29 } 30 31 /* Big endian requires we byte-sapped the little-endian encoded number */ 32 version(BigEndian) 33 { 34 byte[] swappedLength; 35 swappedLength.length = 4; 36 37 swappedLength[0] = messageLengthBytes[3]; 38 swappedLength[1] = messageLengthBytes[2]; 39 swappedLength[2] = messageLengthBytes[1]; 40 swappedLength[3] = messageLengthBytes[0]; 41 42 messageLength = *cast(int*)swappedLength.ptr; 43 } 44 45 46 /* Read the full message */ 47 receiveBuffer = bformatBytes[4..4+messageLength]; 48 49 return receiveBuffer; 50 } 51 52 /** 53 * Encodes the provided message into the bformat format 54 * 55 * Params: 56 * message = the buffer containing bytes to encode 57 * Returns: the encoded payload 58 */ 59 public byte[] encodeBformat(byte[] message) 60 { 61 /* The message buffer */ 62 byte[] messageBuffer; 63 64 /* Encode the 4 byte message length header (little endian) */ 65 int payloadLength = cast(int)message.length; 66 byte* lengthBytes = cast(byte*)&payloadLength; 67 68 /* On little endian simply get the bytes as is (it would be encoded as little endian) */ 69 version(LittleEndian) 70 { 71 messageBuffer ~= *(lengthBytes+0); 72 messageBuffer ~= *(lengthBytes+1); 73 messageBuffer ~= *(lengthBytes+2); 74 messageBuffer ~= *(lengthBytes+3); 75 } 76 77 /* On Big Endian you must swap the big-endian-encoded number to be in little endian ordering */ 78 version(BigEndian) 79 { 80 messageBuffer ~= *(lengthBytes+3); 81 messageBuffer ~= *(lengthBytes+2); 82 messageBuffer ~= *(lengthBytes+1); 83 messageBuffer ~= *(lengthBytes+0); 84 } 85 86 87 /* Add the message to the buffer */ 88 messageBuffer ~= cast(byte[])message; 89 90 return messageBuffer; 91 } 92 93 version(unittest) 94 { 95 import std.string : cmp; 96 } 97 98 unittest 99 { 100 string message = "This is my message"; 101 byte[] bformatEncoded = encodeBformat(cast(byte[])message); 102 103 byte[] decodedMessageBytes = decodeMessage(bformatEncoded); 104 string decodedMessage = cast(string)decodedMessageBytes; 105 106 assert(cmp(message, decodedMessage) == 0); 107 }