namespace Hazel { /// /// Extension functions for (en/de)coding integer values /// public static class ByteSpanBigEndianExtensions { // Write a 16-bit integer in big-endian format to output[0..2) public static void WriteBigEndian16(this ByteSpan output, ushort value, int offset = 0) { output[offset + 0] = (byte)(value >> 8); output[offset + 1] = (byte)(value >> 0); } // Write a 24-bit integer in big-endian format to output[0..3) public static void WriteBigEndian24(this ByteSpan output, uint value, int offset = 0) { output[offset + 0] = (byte)(value >> 16); output[offset + 1] = (byte)(value >> 8); output[offset + 2] = (byte)(value >> 0); } // Write a 32-bit integer in big-endian format to output[0..4) public static void WriteBigEndian32(this ByteSpan output, uint value, int offset) { output[offset + 0] = (byte)(value >> 24); output[offset + 1] = (byte)(value >> 16); output[offset + 2] = (byte)(value >> 8); output[offset + 3] = (byte)(value >> 0); } // Write a 48-bit integer in big-endian format to output[0..6) public static void WriteBigEndian48(this ByteSpan output, ulong value, int offset = 0) { output[offset + 0] = (byte)(value >> 40); output[offset + 1] = (byte)(value >> 32); output[offset + 2] = (byte)(value >> 24); output[offset + 3] = (byte)(value >> 16); output[offset + 4] = (byte)(value >> 8); output[offset + 5] = (byte)(value >> 0); } // Write a 64-bit integer in big-endian format to output[0..8) public static void WriteBigEndian64(this ByteSpan output, ulong value, int offset = 0) { output[offset + 0] = (byte)(value >> 56); output[offset + 1] = (byte)(value >> 48); output[offset + 2] = (byte)(value >> 40); output[offset + 3] = (byte)(value >> 32); output[offset + 4] = (byte)(value >> 24); output[offset + 5] = (byte)(value >> 16); output[offset + 6] = (byte)(value >> 8); output[offset + 7] = (byte)(value >> 0); } // Read a 16-bit integer in big-endian format from input[0..2) public static ushort ReadBigEndian16(this ByteSpan input, int offset = 0) { ushort value = 0; value |= (ushort)(input[offset + 0] << 8); value |= (ushort)(input[offset + 1] << 0); return value; } // Read a 24-bit integer in big-endian format from input[0..3) public static uint ReadBigEndian24(this ByteSpan input, int offset = 0) { uint value = 0; value |= (uint)input[offset + 0] << 16; value |= (uint)input[offset + 1] << 8; value |= (uint)input[offset + 2] << 0; return value; } // Read a 48-bit integer in big-endian format from input[0..3) public static ulong ReadBigEndian48(this ByteSpan input, int offset = 0) { ulong value = 0; value |= (ulong)input[offset + 0] << 40; value |= (ulong)input[offset + 1] << 32; value |= (ulong)input[offset + 2] << 24; value |= (ulong)input[offset + 3] << 16; value |= (ulong)input[offset + 4] << 8; value |= (ulong)input[offset + 5] << 0; return value; } } public static class ByteSpanLittleEndianExtensions { // Read a 24-bit integer in little-endian format from input[0..3) public static uint ReadLittleEndian24(this ByteSpan input, int offset = 0) { uint value = 0; value |= (uint)input[offset + 0]; value |= (uint)input[offset + 1] << 8; value |= (uint)input[offset + 2] << 16; return value; } // Read a 24-bit integer in little-endian format from input[0..4) public static uint ReadLittleEndian32(this ByteSpan input, int offset = 0) { uint value = 0; value |= (uint)input[offset + 0]; value |= (uint)input[offset + 1] << 8; value |= (uint)input[offset + 2] << 16; value |= (uint)input[offset + 3] << 24; return value; } /// /// Reuse an existing span if there is enough space, /// otherwise allocate new storage /// /// /// Source span we should attempt to reuse /// /// Required size (bytes) public static ByteSpan ReuseSpanIfPossible(this ByteSpan source, int requiredSize) { if (source.Length >= requiredSize) { return source.Slice(0, requiredSize); } return new byte[requiredSize]; } } }