diff options
Diffstat (limited to 'Tools/Hazel-Networking/Hazel/ByteSpanExtensions.cs')
-rw-r--r-- | Tools/Hazel-Networking/Hazel/ByteSpanExtensions.cs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/Tools/Hazel-Networking/Hazel/ByteSpanExtensions.cs b/Tools/Hazel-Networking/Hazel/ByteSpanExtensions.cs new file mode 100644 index 0000000..3a9d1ac --- /dev/null +++ b/Tools/Hazel-Networking/Hazel/ByteSpanExtensions.cs @@ -0,0 +1,131 @@ +namespace Hazel +{ + /// <summary> + /// Extension functions for (en/de)coding integer values + /// </summary> + 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; + } + + /// <summary> + /// Reuse an existing span if there is enough space, + /// otherwise allocate new storage + /// </summary> + /// <param name="source"> + /// Source span we should attempt to reuse + /// </param> + /// <param name="requiredSize">Required size (bytes)</param> + public static ByteSpan ReuseSpanIfPossible(this ByteSpan source, int requiredSize) + { + if (source.Length >= requiredSize) + { + return source.Slice(0, requiredSize); + } + + return new byte[requiredSize]; + } + + } +} |