From 7ba30d701eb3f3497fab44022ec7e2a8b74a7ce4 Mon Sep 17 00:00:00 2001 From: Robert Hague Date: Fri, 26 Jan 2024 14:17:03 +0100 Subject: [PATCH] Use BinaryPrimitives in Pack --- src/Renci.SshNet/Common/Pack.cs | 139 +++++++++++++++++--------------- 1 file changed, 75 insertions(+), 64 deletions(-) diff --git a/src/Renci.SshNet/Common/Pack.cs b/src/Renci.SshNet/Common/Pack.cs index fd8626623..d8b39d4ea 100644 --- a/src/Renci.SshNet/Common/Pack.cs +++ b/src/Renci.SshNet/Common/Pack.cs @@ -1,4 +1,9 @@ -namespace Renci.SshNet.Common +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER +using System; +using System.Buffers.Binary; +#endif + +namespace Renci.SshNet.Common { /// /// Provides convenience methods for conversion to and from both Big Endian and Little Endian. @@ -12,24 +17,13 @@ internal static class Pack /// Converted . internal static ushort LittleEndianToUInt16(byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt16LittleEndian(buffer); +#else ushort n = buffer[0]; n |= (ushort) (buffer[1] << 8); return n; - } - - /// - /// Converts little endian bytes into number. - /// - /// The buffer. - /// The buffer offset. - /// Converted . - internal static uint LittleEndianToUInt32(byte[] buffer, int offset) - { - uint n = buffer[offset]; - n |= (uint) buffer[offset + 1] << 8; - n |= (uint) buffer[offset + 2] << 16; - n |= (uint) buffer[offset + 3] << 24; - return n; +#endif } /// @@ -39,11 +33,15 @@ internal static uint LittleEndianToUInt32(byte[] buffer, int offset) /// Converted . internal static uint LittleEndianToUInt32(byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt32LittleEndian(buffer); +#else uint n = buffer[0]; n |= (uint) buffer[1] << 8; n |= (uint) buffer[2] << 16; n |= (uint) buffer[3] << 24; return n; +#endif } /// @@ -53,6 +51,9 @@ internal static uint LittleEndianToUInt32(byte[] buffer) /// Converted . internal static ulong LittleEndianToUInt64(byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt64LittleEndian(buffer); +#else ulong n = buffer[0]; n |= (ulong) buffer[1] << 8; n |= (ulong) buffer[2] << 16; @@ -62,6 +63,7 @@ internal static ulong LittleEndianToUInt64(byte[] buffer) n |= (ulong) buffer[6] << 48; n |= (ulong) buffer[7] << 56; return n; +#endif } /// @@ -80,10 +82,14 @@ internal static byte[] UInt16ToLittleEndian(ushort value) /// /// The number to convert. /// The buffer. - internal static void UInt16ToLittleEndian(ushort value, byte[] buffer) + private static void UInt16ToLittleEndian(ushort value, byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt16LittleEndian(buffer, value); +#else buffer[0] = (byte) (value & 0x00FF); buffer[1] = (byte) ((value & 0xFF00) >> 8); +#endif } /// @@ -102,26 +108,16 @@ internal static byte[] UInt32ToLittleEndian(uint value) /// /// The number to convert. /// The buffer. - internal static void UInt32ToLittleEndian(uint value, byte[] buffer) + private static void UInt32ToLittleEndian(uint value, byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); +#else buffer[0] = (byte) (value & 0x000000FF); buffer[1] = (byte) ((value & 0x0000FF00) >> 8); buffer[2] = (byte) ((value & 0x00FF0000) >> 16); buffer[3] = (byte) ((value & 0xFF000000) >> 24); - } - - /// - /// Populates buffer with little endian number representation. - /// - /// The number to convert. - /// The buffer. - /// The buffer offset. - internal static void UInt32ToLittleEndian(uint value, byte[] buffer, int offset) - { - buffer[offset] = (byte) (value & 0x000000FF); - buffer[offset + 1] = (byte) ((value & 0x0000FF00) >> 8); - buffer[offset + 2] = (byte) ((value & 0x00FF0000) >> 16); - buffer[offset + 3] = (byte) ((value & 0xFF000000) >> 24); +#endif } /// @@ -140,8 +136,11 @@ internal static byte[] UInt64ToLittleEndian(ulong value) /// /// The number to convert. /// The buffer. - internal static void UInt64ToLittleEndian(ulong value, byte[] buffer) + private static void UInt64ToLittleEndian(ulong value, byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); +#else buffer[0] = (byte) (value & 0x00000000000000FF); buffer[1] = (byte) ((value & 0x000000000000FF00) >> 8); buffer[2] = (byte) ((value & 0x0000000000FF0000) >> 16); @@ -150,41 +149,41 @@ internal static void UInt64ToLittleEndian(ulong value, byte[] buffer) buffer[5] = (byte) ((value & 0x0000FF0000000000) >> 40); buffer[6] = (byte) ((value & 0x00FF000000000000) >> 48); buffer[7] = (byte) ((value & 0xFF00000000000000) >> 56); +#endif } internal static byte[] UInt16ToBigEndian(ushort value) { var buffer = new byte[2]; - UInt16ToBigEndian(value, buffer); + UInt16ToBigEndian(value, buffer, offset: 0); return buffer; } - internal static void UInt16ToBigEndian(ushort value, byte[] buffer) - { - buffer[0] = (byte) (value >> 8); - buffer[1] = (byte) (value & 0x00FF); - } - internal static void UInt16ToBigEndian(ushort value, byte[] buffer, int offset) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(offset), value); +#else buffer[offset] = (byte) (value >> 8); buffer[offset + 1] = (byte) (value & 0x00FF); +#endif } internal static void UInt32ToBigEndian(uint value, byte[] buffer) { - buffer[0] = (byte) ((value & 0xFF000000) >> 24); - buffer[1] = (byte) ((value & 0x00FF0000) >> 16); - buffer[2] = (byte) ((value & 0x0000FF00) >> 8); - buffer[3] = (byte) (value & 0x000000FF); + UInt32ToBigEndian(value, buffer, offset: 0); } internal static void UInt32ToBigEndian(uint value, byte[] buffer, int offset) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(offset), value); +#else buffer[offset++] = (byte) ((value & 0xFF000000) >> 24); buffer[offset++] = (byte) ((value & 0x00FF0000) >> 16); buffer[offset++] = (byte) ((value & 0x0000FF00) >> 8); buffer[offset] = (byte) (value & 0x000000FF); +#endif } internal static byte[] UInt32ToBigEndian(uint value) @@ -194,24 +193,27 @@ internal static byte[] UInt32ToBigEndian(uint value) return buffer; } - /// - /// Returns the specified 64-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. internal static byte[] UInt64ToBigEndian(ulong value) { - return new[] - { - (byte) ((value & 0xFF00000000000000) >> 56), - (byte) ((value & 0x00FF000000000000) >> 48), - (byte) ((value & 0x0000FF0000000000) >> 40), - (byte) ((value & 0x000000FF00000000) >> 32), - (byte) ((value & 0x00000000FF000000) >> 24), - (byte) ((value & 0x0000000000FF0000) >> 16), - (byte) ((value & 0x000000000000FF00) >> 8), - (byte) (value & 0x00000000000000FF) - }; + var buffer = new byte[8]; + UInt64ToBigEndian(value, buffer, offset: 0); + return buffer; + } + + private static void UInt64ToBigEndian(ulong value, byte[] buffer, int offset) + { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + BinaryPrimitives.WriteUInt64BigEndian(buffer.AsSpan(offset), value); +#else + buffer[offset++] = (byte) ((value & 0xFF00000000000000) >> 56); + buffer[offset++] = (byte) ((value & 0x00FF000000000000) >> 48); + buffer[offset++] = (byte) ((value & 0x0000FF0000000000) >> 40); + buffer[offset++] = (byte) ((value & 0x000000FF00000000) >> 32); + buffer[offset++] = (byte) ((value & 0x00000000FF000000) >> 24); + buffer[offset++] = (byte) ((value & 0x0000000000FF0000) >> 16); + buffer[offset++] = (byte) ((value & 0x000000000000FF00) >> 8); + buffer[offset] = (byte) (value & 0x00000000000000FF); +#endif } /// @@ -221,7 +223,11 @@ internal static byte[] UInt64ToBigEndian(ulong value) /// Converted . internal static ushort BigEndianToUInt16(byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt16BigEndian(buffer); +#else return (ushort) (buffer[0] << 8 | buffer[1]); +#endif } /// @@ -232,10 +238,14 @@ internal static ushort BigEndianToUInt16(byte[] buffer) /// Converted . internal static uint BigEndianToUInt32(byte[] buffer, int offset) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt32BigEndian(buffer.AsSpan(offset)); +#else return (uint) buffer[offset + 0] << 24 | (uint) buffer[offset + 1] << 16 | (uint) buffer[offset + 2] << 8 | buffer[offset + 3]; +#endif } /// @@ -245,10 +255,7 @@ internal static uint BigEndianToUInt32(byte[] buffer, int offset) /// Converted . internal static uint BigEndianToUInt32(byte[] buffer) { - return (uint) buffer[0] << 24 | - (uint) buffer[1] << 16 | - (uint) buffer[2] << 8 | - buffer[3]; + return BigEndianToUInt32(buffer, offset: 0); } /// @@ -258,6 +265,9 @@ internal static uint BigEndianToUInt32(byte[] buffer) /// Converted . internal static ulong BigEndianToUInt64(byte[] buffer) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return BinaryPrimitives.ReadUInt64BigEndian(buffer); +#else return (ulong) buffer[0] << 56 | (ulong) buffer[1] << 48 | (ulong) buffer[2] << 40 | @@ -266,6 +276,7 @@ internal static ulong BigEndianToUInt64(byte[] buffer) (ulong) buffer[5] << 16 | (ulong) buffer[6] << 8 | buffer[7]; +#endif } } }