Skip to content

Commit 5421da8

Browse files
authored
Add big-endian conversion methods to Endianness
Signed-off-by: Xen <lordofxen@deskasoft.com>
1 parent 95cd658 commit 5421da8

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

HashifyNet/Core/Utilities/Endianness.cs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,47 @@ public static void ToLittleEndianBytes(ulong value, byte[] buffer, int offset)
8383
buffer[offset + 7] = (byte)(value >> 56);
8484
}
8585

86+
/// <summary>
87+
/// Converts the specified 32-bit unsigned integer to its big-endian byte representation and writes the result to
88+
/// the specified buffer at the given offset.
89+
/// </summary>
90+
/// <remarks>This method writes exactly 4 bytes to the buffer, starting at the specified offset. Ensure that
91+
/// the buffer has sufficient capacity to accommodate the bytes being written.</remarks>
92+
/// <param name="value">The 32-bit unsigned integer to convert.</param>
93+
/// <param name="buffer">The byte array to which the big-endian representation will be written.</param>
94+
/// <param name="offset">The zero-based index in the buffer at which to begin writing the bytes.</param>
95+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
96+
public static void ToBigEndianBytes(uint value, byte[] buffer, int offset)
97+
{
98+
buffer[offset] = (byte)(value >> 24);
99+
buffer[offset + 1] = (byte)(value >> 16);
100+
buffer[offset + 2] = (byte)(value >> 8);
101+
buffer[offset + 3] = (byte)value;
102+
}
103+
104+
/// <summary>
105+
/// Converts the specified 64-bit unsigned integer to its big-endian byte representation and writes the result to
106+
/// the specified buffer at the given offset.
107+
/// </summary>
108+
/// <remarks>This method writes the most significant byte of <paramref name="value"/> to <paramref
109+
/// name="buffer"/> at the specified <paramref name="offset"/>, followed by the remaining bytes in decreasing order
110+
/// of significance.</remarks>
111+
/// <param name="value">The 64-bit unsigned integer to convert.</param>
112+
/// <param name="buffer">The byte array to which the big-endian representation of <paramref name="value"/> will be written.</param>
113+
/// <param name="offset">The zero-based index in <paramref name="buffer"/> at which to begin writing the bytes.</param>
114+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
115+
public static void ToBigEndianBytes(ulong value, byte[] buffer, int offset)
116+
{
117+
buffer[offset] = (byte)(value >> 56);
118+
buffer[offset + 1] = (byte)(value >> 48);
119+
buffer[offset + 2] = (byte)(value >> 40);
120+
buffer[offset + 3] = (byte)(value >> 32);
121+
buffer[offset + 4] = (byte)(value >> 24);
122+
buffer[offset + 5] = (byte)(value >> 16);
123+
buffer[offset + 6] = (byte)(value >> 8);
124+
buffer[offset + 7] = (byte)value;
125+
}
126+
86127
/// <summary>
87128
/// Converts the specified 64-bit unsigned integer to little-endian format.
88129
/// </summary>
@@ -104,6 +145,28 @@ public static ulong ToLittleEndian(ulong value)
104145
return BinaryPrimitives.ReverseEndianness(value);
105146
}
106147

148+
149+
/// <summary>
150+
/// Converts the specified 64-bit unsigned integer to big-endian format.
151+
/// </summary>
152+
/// <remarks>This method ensures that the returned value is in big-endian format, regardless of the
153+
/// system's endianness. It is optimized for performance and uses aggressive inlining.</remarks>
154+
/// <param name="value">The 64-bit unsigned integer to convert.</param>
155+
/// <returns>The value in big-endian format. If the system architecture is already big-endian, the original value is
156+
/// returned unchanged. Otherwise, the byte order is reversed.</returns>
157+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
158+
public static ulong ToBigEndian(ulong value)
159+
{
160+
// If the system architecture is already big-endian, the value doesn't need to be changed.
161+
if (!BitConverter.IsLittleEndian)
162+
{
163+
return value;
164+
}
165+
166+
// If the system is little-endian, we must reverse the byte order to make it big-endian.
167+
return BinaryPrimitives.ReverseEndianness(value);
168+
}
169+
107170
/// <summary>
108171
/// Converts a sequence of 8 bytes from the specified buffer, starting at the given offset, into a 64-bit unsigned
109172
/// integer using little-endian byte order.
@@ -185,6 +248,87 @@ public static uint ToUInt32LittleEndian(ReadOnlySpan<byte> buffer, int offset)
185248
((uint)buffer[offset + 3] << 24);
186249
}
187250

251+
/// <summary>
252+
/// Converts a sequence of 8 bytes from the specified buffer, starting at the given offset, into a 64-bit unsigned
253+
/// integer using big-endian byte order.
254+
/// </summary>
255+
/// <param name="buffer">The byte array containing the data to convert. Must contain at least 8 bytes starting from <paramref
256+
/// name="offset"/>.</param>
257+
/// <param name="offset">The zero-based index in <paramref name="buffer"/> at which to begin reading the 8 bytes.</param>
258+
/// <returns>A 64-bit unsigned integer representing the big-endian interpretation of the 8 bytes starting at <paramref
259+
/// name="offset"/>.</returns>
260+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
261+
public static ulong ToUInt64BigEndian(byte[] buffer, int offset)
262+
{
263+
return ((ulong)buffer[offset] << 56) |
264+
((ulong)buffer[offset + 1] << 48) |
265+
((ulong)buffer[offset + 2] << 40) |
266+
((ulong)buffer[offset + 3] << 32) |
267+
((ulong)buffer[offset + 4] << 24) |
268+
((ulong)buffer[offset + 5] << 16) |
269+
((ulong)buffer[offset + 6] << 8) |
270+
buffer[offset + 7];
271+
}
272+
273+
/// <summary>
274+
/// Converts a sequence of bytes from the specified buffer, starting at the given offset, into a 64-bit unsigned
275+
/// integer using big-endian byte order.
276+
/// </summary>
277+
/// <remarks>This method assumes that the bytes in the buffer are stored in big-endian format, where the
278+
/// most significant byte comes first.</remarks>
279+
/// <param name="buffer">The buffer containing the bytes to convert. Must have at least 8 bytes available starting from <paramref
280+
/// name="offset"/>.</param>
281+
/// <param name="offset">The zero-based index in <paramref name="buffer"/> at which to begin reading the bytes.</param>
282+
/// <returns>A 64-bit unsigned integer constructed from the 8 bytes starting at <paramref name="offset"/> in big-endian
283+
/// order.</returns>
284+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
285+
public static ulong ToUInt64BigEndian(ReadOnlySpan<byte> buffer, int offset)
286+
{
287+
return ((ulong)buffer[offset] << 56) |
288+
((ulong)buffer[offset + 1] << 48) |
289+
((ulong)buffer[offset + 2] << 40) |
290+
((ulong)buffer[offset + 3] << 32) |
291+
((ulong)buffer[offset + 4] << 24) |
292+
((ulong)buffer[offset + 5] << 16) |
293+
((ulong)buffer[offset + 6] << 8) |
294+
buffer[offset + 7];
295+
}
296+
297+
/// <summary>
298+
/// Converts a sequence of four bytes from the specified buffer, starting at the given offset, into a 32-bit unsigned
299+
/// integer using big-endian byte order.
300+
/// </summary>
301+
/// <param name="buffer">The byte array containing the data to convert. Must contain at least four bytes starting from <paramref
302+
/// name="offset"/>.</param>
303+
/// <param name="offset">The zero-based index in <paramref name="buffer"/> at which to begin reading the four bytes.</param>
304+
/// <returns>A 32-bit unsigned integer representing the value of the four bytes in big-endian order.</returns>
305+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
306+
public static uint ToUInt32BigEndian(byte[] buffer, int offset)
307+
{
308+
return ((uint)buffer[offset] << 24) |
309+
((uint)buffer[offset + 1] << 16) |
310+
((uint)buffer[offset + 2] << 8) |
311+
buffer[offset + 3];
312+
}
313+
314+
/// <summary>
315+
/// Converts a sequence of bytes from a specified offset in a buffer to a 32-bit unsigned integer, assuming
316+
/// big-endian byte order.
317+
/// </summary>
318+
/// <param name="buffer">The buffer containing the bytes to convert. Must have at least four bytes available starting at the specified
319+
/// offset.</param>
320+
/// <param name="offset">The zero-based index in the buffer at which to begin reading the bytes.</param>
321+
/// <returns>A 32-bit unsigned integer representing the value of the four bytes starting at the specified offset, interpreted
322+
/// as big-endian.</returns>
323+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
324+
public static uint ToUInt32BigEndian(ReadOnlySpan<byte> buffer, int offset)
325+
{
326+
return ((uint)buffer[offset] << 24) |
327+
((uint)buffer[offset + 1] << 16) |
328+
((uint)buffer[offset + 2] << 8) |
329+
buffer[offset + 3];
330+
}
331+
188332
/// <summary>
189333
/// Converts the specified 64-bit unsigned integer to an array of bytes in little-endian order.
190334
/// </summary>
@@ -210,5 +354,31 @@ public static byte[] GetBytesLittleEndian(uint value)
210354
ToLittleEndianBytes(value, bytes, 0);
211355
return bytes;
212356
}
357+
358+
/// <summary>
359+
/// Converts the specified 64-bit unsigned integer to an array of bytes in big-endian order.
360+
/// </summary>
361+
/// <param name="value">The 64-bit unsigned integer to convert.</param>
362+
/// <returns>An array of 8 bytes representing the <paramref name="value"/> in big-endian order.</returns>
363+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
364+
public static byte[] GetBytesBigEndian(ulong value)
365+
{
366+
byte[] bytes = new byte[8];
367+
ToBigEndianBytes(value, bytes, 0);
368+
return bytes;
369+
}
370+
371+
/// <summary>
372+
/// Converts the specified 32-bit unsigned integer to a byte array in big-endian format.
373+
/// </summary>
374+
/// <param name="value">The 32-bit unsigned integer to convert.</param>
375+
/// <returns>A byte array containing the big-endian representation of the specified value.</returns>
376+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
377+
public static byte[] GetBytesBigEndian(uint value)
378+
{
379+
byte[] bytes = new byte[4];
380+
ToBigEndianBytes(value, bytes, 0);
381+
return bytes;
382+
}
213383
}
214384
}

0 commit comments

Comments
 (0)