1 // Written in the D programming language. 2 3 /** 4 The module provides tools for assembling and disassembling variable-length byte sequences that are found in different messages in the 9P / Styx protocol. 5 6 Copyright: LightHouse Software, 2021 7 License: $(HTTP https://github.com/aquaratixc/ESL-License, Experimental Software License 1.0). 8 Authors: Oleg Bakharev, 9 Ilya Pertsev 10 */ 11 module styx2000.lowlevel.vls; 12 13 private { 14 import styx2000.lowlevel.endianness : fromLEBytes, toLEBytes; 15 } 16 17 /** 18 A class that provides methods for unpacking and packing sequences of bytes into an array of unsigned bytes with an indicator of the number of elements in the sequence. 19 The number of elements is written in little-endian byte order at the beginning of each variable-length sequence and is the two bytes preceding the main data. 20 The static methods of this class allow packing and unpacking 9P / Styx protocol sequences (hereinafter we will denote such sequences as `VLS` - `Variable Length Sequences`). 21 */ 22 class VariableLengthSequence 23 { 24 /** 25 Encode byte sequence as VLS 26 Params: 27 bytes = Array of unsigned bytes for constructing VLS. 28 29 Typical usage: 30 ---- 31 // return array [3, 0, 0, 1, 2] 32 auto vls = VariableLengthSequence.pack([0x00, 0x01, 0x02]); 33 ---- 34 */ 35 static ubyte[] pack(ubyte[] bytes...) 36 { 37 ubyte[] rawBytes; 38 39 auto fieldSize = cast(ushort) bytes.length; 40 rawBytes ~= toLEBytes!ushort(fieldSize); 41 rawBytes ~= bytes; 42 43 return rawBytes; 44 } 45 46 /** 47 Decode byte sequence from VLS 48 Params: 49 bytes = Array of unsigned bytes for constructing VLS. 50 Throws: 51 Exception on empty bytes array. 52 53 Typical usage: 54 ---- 55 // return array [0, 1, 2] 56 auto vls = VariableLengthSequence.unpack([3, 0, 0, 1, 2]); 57 ---- 58 */ 59 static ubyte[] unpack(ubyte[] bytes...) 60 { 61 ubyte[] rawBytes; 62 63 if (bytes.length == 0) 64 { 65 throw new Exception(`Wrong size of Variable Length Sequence (VLS)`); 66 } 67 else 68 { 69 auto fieldSize = fromLEBytes!ushort(bytes[0..2]); 70 rawBytes = bytes[2..2+fieldSize]; 71 } 72 73 return rawBytes; 74 } 75 }