1 // Written in the D programming language. 2 3 /** 4 Module for manipulating bytes in constructing and deconstructing various byte orders. 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.endianness; 12 13 /// Endianess (i.e byte-order) 14 enum BYTE_ORDER 15 { 16 /// Little-endian byte-order 17 LITTLE_ENDIAN, 18 /// Big-endian byte-order 19 BIG_ENDIAN 20 } 21 22 23 /** 24 A class that provides functionality for construct and deconstruct values. All methods is static. 25 */ 26 class EndianSequence(BYTE_ORDER byteOrder) 27 { 28 /** 29 Constructs (restores) a value from the passed in byte array. 30 Params: 31 byteOrder = Byte order for value (little or big endian). 32 bytes = Array of unsigned bytes for reconstructing value. 33 34 Typical usage: 35 ---- 36 uint tmp = EndianSequence!(BYTE_ORDER.LITTLE_ENDIAN).unpack!uint([0xab, 0xcd, 0xef, 0x00]); 37 ---- 38 */ 39 private { 40 import std.traits : isBasicType; 41 42 static auto shiftOf(T)(T i) if (isBasicType!T) 43 { 44 static if (byteOrder == BYTE_ORDER.LITTLE_ENDIAN) 45 return i << 3; 46 else 47 return (T.sizeof - i - 1) << 3; 48 } 49 } 50 51 static T unpack(T)(ubyte[] bytes...) 52 { 53 T result; 54 55 foreach (i, e; bytes) 56 { 57 result |= (e << shiftOf(i)); 58 } 59 60 return result; 61 } 62 63 /** 64 Deconstructs (saves) a passed value to unsigned byte array. 65 Params: 66 byteOrder = Byte order for value (little or big endian). 67 value = Value for deconstructing. 68 69 Typical usage: 70 ---- 71 ubyte[] tmp = EndianSequence!(BYTE_ORDER.LITTLE_ENDIAN).pack!uint(150_000); 72 ---- 73 */ 74 static ubyte[] pack(T)(T value) 75 { 76 ubyte[] data; 77 T mask = T(0xff); 78 79 foreach (i; 0 .. T.sizeof) 80 { 81 auto shift = shiftOf(i); 82 data ~= cast(ubyte) ((value & (mask << shift)) >> shift); 83 } 84 85 return data; 86 } 87 } 88 89 90 /** 91 Parse a value into bytes in little-endian order. Helper for EndianSequence.pack with preset Little Endian byte order (LE). 92 Params: 93 value = Value for parsing. 94 Returns: An array of unsigned bytes representing the value passed as a parameter in little-endian order 95 96 97 Typical usage: 98 ---- 99 ubyte[] tmp = toLEBytes!uint(150_000); 100 ---- 101 */ 102 alias toLEBytes = EndianSequence!(BYTE_ORDER.LITTLE_ENDIAN).pack; 103 104 /** 105 Construct a value from bytes fed in little-endian order. Helper for EndianSequence.unpack with preset Little Endian byte order (LE). 106 Params: 107 bytes = An array of unsigned bytes (little-endian-order). 108 Returns: The value retrieved from the array 109 110 111 Typical usage: 112 ---- 113 // value is 0x00efcdab in hex or 15715755 in dec 114 uint tmp = fromLEBytes!uint([0xab, 0xcd, 0xef, 0x00]); 115 ---- 116 */ 117 alias fromLEBytes = EndianSequence!(BYTE_ORDER.LITTLE_ENDIAN).unpack; 118 119 /** 120 Parse a value into bytes in big-endian order. Helper for EndianSequence.pack with preset Big Endian byte order (BE). 121 Params: 122 value = Value for parsing. 123 Returns: An array of unsigned bytes representing the value passed as a parameter in little-endian order 124 125 126 Typical usage: 127 ---- 128 ubyte[] tmp = toBEBytes!uint(150_000); 129 ---- 130 */ 131 alias toBEBytes = EndianSequence!(BYTE_ORDER.BIG_ENDIAN).pack; 132 133 /** 134 Construct a value from bytes fed in big-endian order. Helper for EndianSequence.unpack with preset Big Endian byte order (BE). 135 Params: 136 bytes = An array of unsigned bytes (big-endian-order). 137 Returns: The value retrieved from the array 138 139 140 Typical usage: 141 ---- 142 // value is 0xabcdef00 in hex or 2882400000 in dec 143 uint tmp = fromBEBytes!uint([0xab, 0xcd, 0xef, 0x00]); 144 ---- 145 */ 146 alias fromLEBytes = EndianSequence!(BYTE_ORDER.LITTLE_ENDIAN).unpack;