Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use BinaryPrimitives in Pack #1305

Merged
merged 1 commit into from
Feb 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 75 additions & 64 deletions src/Renci.SshNet/Common/Pack.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Provides convenience methods for conversion to and from both Big Endian and Little Endian.
Expand All @@ -12,24 +17,13 @@ internal static class Pack
/// <returns>Converted <see cref="ushort" />.</returns>
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;
}

/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns>Converted <see cref="uint" />.</returns>
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
}

/// <summary>
Expand All @@ -39,11 +33,15 @@ internal static uint LittleEndianToUInt32(byte[] buffer, int offset)
/// <returns>Converted <see cref="uint" />.</returns>
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
}

/// <summary>
Expand All @@ -53,6 +51,9 @@ internal static uint LittleEndianToUInt32(byte[] buffer)
/// <returns>Converted <see cref="ulong" />.</returns>
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;
Expand All @@ -62,6 +63,7 @@ internal static ulong LittleEndianToUInt64(byte[] buffer)
n |= (ulong) buffer[6] << 48;
n |= (ulong) buffer[7] << 56;
return n;
#endif
}

/// <summary>
Expand All @@ -80,10 +82,14 @@ internal static byte[] UInt16ToLittleEndian(ushort value)
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
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
}

/// <summary>
Expand All @@ -102,26 +108,16 @@ internal static byte[] UInt32ToLittleEndian(uint value)
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
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);
}

/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
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
}

/// <summary>
Expand All @@ -140,8 +136,11 @@ internal static byte[] UInt64ToLittleEndian(ulong value)
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
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);
Expand All @@ -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)
Expand All @@ -194,24 +193,27 @@ internal static byte[] UInt32ToBigEndian(uint value)
return buffer;
}

/// <summary>
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
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
}

/// <summary>
Expand All @@ -221,7 +223,11 @@ internal static byte[] UInt64ToBigEndian(ulong value)
/// <returns>Converted <see cref="ushort" />.</returns>
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
}

/// <summary>
Expand All @@ -232,10 +238,14 @@ internal static ushort BigEndianToUInt16(byte[] buffer)
/// <returns>Converted <see cref="uint" />.</returns>
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
}

/// <summary>
Expand All @@ -245,10 +255,7 @@ internal static uint BigEndianToUInt32(byte[] buffer, int offset)
/// <returns>Converted <see cref="uint" />.</returns>
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);
}

/// <summary>
Expand All @@ -258,6 +265,9 @@ internal static uint BigEndianToUInt32(byte[] buffer)
/// <returns>Converted <see cref="ulong" />.</returns>
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 |
Expand All @@ -266,6 +276,7 @@ internal static ulong BigEndianToUInt64(byte[] buffer)
(ulong) buffer[5] << 16 |
(ulong) buffer[6] << 8 |
buffer[7];
#endif
}
}
}