From 1157e36eff8beaa6f6a8aea0fbd18b0a868d4e96 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Wed, 23 Aug 2023 17:00:55 +0100 Subject: [PATCH] refactor: separate stream Read/Write methods to partials --- X10D/src/IO/StreamExtensions.Reading.cs | 523 +++++++++++++ X10D/src/IO/StreamExtensions.Writing.cs | 473 ++++++++++++ X10D/src/IO/StreamExtensions.cs | 989 +----------------------- 3 files changed, 998 insertions(+), 987 deletions(-) create mode 100644 X10D/src/IO/StreamExtensions.Reading.cs create mode 100644 X10D/src/IO/StreamExtensions.Writing.cs diff --git a/X10D/src/IO/StreamExtensions.Reading.cs b/X10D/src/IO/StreamExtensions.Reading.cs new file mode 100644 index 0000000..b3bc317 --- /dev/null +++ b/X10D/src/IO/StreamExtensions.Reading.cs @@ -0,0 +1,523 @@ +using System.Buffers.Binary; +using System.Runtime.InteropServices; + +namespace X10D.IO; + +public static partial class StreamExtensions +{ + /// + /// Reads an from the current stream as big endian, and advances the stream position by sixteen + /// bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static decimal ReadDecimalBigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + const int decimalSize = sizeof(decimal); + const int int32Size = sizeof(int); + const int partitionSize = decimalSize / int32Size; + + Span buffer = stackalloc int[partitionSize]; + for (var index = 0; index < partitionSize; index++) + { + buffer[index] = stream.ReadInt32BigEndian(); + } + + if (BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + +#if NET5_0_OR_GREATER + return new decimal(buffer); +#else + return new decimal(buffer.ToArray()); +#endif + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by sixteen + /// bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static decimal ReadDecimalLittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + const int decimalSize = sizeof(decimal); + const int int32Size = sizeof(int); + const int partitionSize = decimalSize / int32Size; + + Span buffer = stackalloc int[partitionSize]; + for (var index = 0; index < partitionSize; index++) + { + buffer[index] = stream.ReadInt32LittleEndian(); + } + + if (!BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + +#if NET5_0_OR_GREATER + return new decimal(buffer); +#else + return new decimal(buffer.ToArray()); +#endif + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static double ReadDoubleBigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); +#if NET5_0_OR_GREATER + return BinaryPrimitives.ReadDoubleBigEndian(buffer); +#else + if (BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + + return MemoryMarshal.Read(buffer); +#endif + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by eight + /// bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + public static double ReadDoubleLittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); +#if NET5_0_OR_GREATER + return BinaryPrimitives.ReadDoubleLittleEndian(buffer); +#else + if (!BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + + return MemoryMarshal.Read(buffer); +#endif + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by two bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static short ReadInt16BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[2]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt16BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by two bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + public static short ReadInt16LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[2]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt16LittleEndian(buffer); + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by four bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static int ReadInt32BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt32BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + public static int ReadInt32LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt32LittleEndian(buffer); + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + public static long ReadInt64BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt64BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by eight + /// bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + public static long ReadInt64LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadInt64LittleEndian(buffer); + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by four bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static float ReadSingleBigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); +#if NET5_0_OR_GREATER + return BinaryPrimitives.ReadSingleBigEndian(buffer); +#else + if (BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + + return MemoryMarshal.Read(buffer); +#endif + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by four + /// bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static float ReadSingleLittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); +#if NET5_0_OR_GREATER + return BinaryPrimitives.ReadSingleLittleEndian(buffer); +#else + if (!BitConverter.IsLittleEndian) + { + buffer.Reverse(); + } + + return MemoryMarshal.Read(buffer); +#endif + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by two bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static ushort ReadUInt16BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[2]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt16BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by two bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static ushort ReadUInt16LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[2]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt16LittleEndian(buffer); + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by four bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static uint ReadUInt32BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt32BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static uint ReadUInt32LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[4]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt32LittleEndian(buffer); + } + + /// + /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. + /// + /// The stream from which the value should be read. + /// The big endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static ulong ReadUInt64BigEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt64BigEndian(buffer); + } + + /// + /// Reads an from the current stream as little endian, and advances the stream position by eight + /// bytes. + /// + /// The stream from which the value should be read. + /// The little endian value. + /// is + /// does not support reading. + [CLSCompliant(false)] + public static ulong ReadUInt64LittleEndian(this Stream stream) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + + Span buffer = stackalloc byte[8]; + _ = stream.Read(buffer); + return BinaryPrimitives.ReadUInt64LittleEndian(buffer); + } +} diff --git a/X10D/src/IO/StreamExtensions.Writing.cs b/X10D/src/IO/StreamExtensions.Writing.cs new file mode 100644 index 0000000..787108e --- /dev/null +++ b/X10D/src/IO/StreamExtensions.Writing.cs @@ -0,0 +1,473 @@ +using System.Buffers.Binary; + +namespace X10D.IO; + +public static partial class StreamExtensions +{ + /// + /// Writes a to the current stream as big endian, and advances the stream position by two bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, short value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[2]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as big endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, int value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as big endian, and advances the stream position by eight bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, long value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as big endian, and advances the stream position by two bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteBigEndian(this Stream stream, ushort value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[2]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as big endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteBigEndian(this Stream stream, uint value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as big endian, and advances the stream position by eight bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteBigEndian(this Stream stream, ulong value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, float value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by eight + /// bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, double value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by sixteen + /// bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteBigEndian(this Stream stream, decimal value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[16]; + value.TryWriteBigEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by two bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, short value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[2]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes an to the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, int value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by eight bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, long value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, float value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by eight + /// bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, double value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by sixteen + /// bytes. + /// + /// The stream to which the value should be written. + /// The to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + public static int WriteLittleEndian(this Stream stream, decimal value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[16]; + value.TryWriteLittleEndian(buffer); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by two bytes. + /// + /// The stream to which the value should be written. + /// The two-byte signed integer to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteLittleEndian(this Stream stream, ushort value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[2]; + BinaryPrimitives.WriteUInt16LittleEndian(buffer, value); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by four bytes. + /// + /// The stream to which the value should be written. + /// The two-byte signed integer to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteLittleEndian(this Stream stream, uint value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[4]; + BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); + return stream.WriteInternal(buffer); + } + + /// + /// Writes a to the current stream as little endian, and advances the stream position by eight bytes. + /// + /// The stream to which the value should be written. + /// The two-byte signed integer to write. + /// The number of bytes written to the stream. + /// is . + /// does not support writing. + [CLSCompliant(false)] + public static int WriteLittleEndian(this Stream stream, ulong value) + { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + + Span buffer = stackalloc byte[8]; + BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); + return stream.WriteInternal(buffer); + } + + private static int WriteInternal(this Stream stream, ReadOnlySpan value) + { + long preWritePosition = stream.Position; + stream.Write(value); + return (int)(stream.Position - preWritePosition); + } +} diff --git a/X10D/src/IO/StreamExtensions.cs b/X10D/src/IO/StreamExtensions.cs index ceb34c8..15e50e0 100644 --- a/X10D/src/IO/StreamExtensions.cs +++ b/X10D/src/IO/StreamExtensions.cs @@ -1,6 +1,4 @@ -using System.Buffers.Binary; -using System.Reflection; -using System.Runtime.InteropServices; +using System.Reflection; using System.Security.Cryptography; namespace X10D.IO; @@ -8,7 +6,7 @@ namespace X10D.IO; /// /// IO-related extension methods for . /// -public static class StreamExtensions +public static partial class StreamExtensions { /// /// Returns the hash of the current stream as an array of bytes using the specified hash algorithm. @@ -57,522 +55,6 @@ public static class StreamExtensions return crypt.ComputeHash(stream); } - /// - /// Reads an from the current stream as big endian, and advances the stream position by sixteen - /// bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static decimal ReadDecimalBigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - const int decimalSize = sizeof(decimal); - const int int32Size = sizeof(int); - const int partitionSize = decimalSize / int32Size; - - Span buffer = stackalloc int[partitionSize]; - for (var index = 0; index < partitionSize; index++) - { - buffer[index] = stream.ReadInt32BigEndian(); - } - - if (BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - -#if NET5_0_OR_GREATER - return new decimal(buffer); -#else - return new decimal(buffer.ToArray()); -#endif - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by sixteen - /// bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static decimal ReadDecimalLittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - const int decimalSize = sizeof(decimal); - const int int32Size = sizeof(int); - const int partitionSize = decimalSize / int32Size; - - Span buffer = stackalloc int[partitionSize]; - for (var index = 0; index < partitionSize; index++) - { - buffer[index] = stream.ReadInt32LittleEndian(); - } - - if (!BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - -#if NET5_0_OR_GREATER - return new decimal(buffer); -#else - return new decimal(buffer.ToArray()); -#endif - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static double ReadDoubleBigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); -#if NET5_0_OR_GREATER - return BinaryPrimitives.ReadDoubleBigEndian(buffer); -#else - if (BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - - return MemoryMarshal.Read(buffer); -#endif - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by eight - /// bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - public static double ReadDoubleLittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); -#if NET5_0_OR_GREATER - return BinaryPrimitives.ReadDoubleLittleEndian(buffer); -#else - if (!BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - - return MemoryMarshal.Read(buffer); -#endif - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by two bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static short ReadInt16BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[2]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt16BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by two bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - public static short ReadInt16LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[2]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt16LittleEndian(buffer); - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by four bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static int ReadInt32BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt32BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - public static int ReadInt32LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt32LittleEndian(buffer); - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - public static long ReadInt64BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt64BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by eight - /// bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - public static long ReadInt64LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadInt64LittleEndian(buffer); - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by four bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static float ReadSingleBigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); -#if NET5_0_OR_GREATER - return BinaryPrimitives.ReadSingleBigEndian(buffer); -#else - if (BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - - return MemoryMarshal.Read(buffer); -#endif - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by four - /// bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static float ReadSingleLittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); -#if NET5_0_OR_GREATER - return BinaryPrimitives.ReadSingleLittleEndian(buffer); -#else - if (!BitConverter.IsLittleEndian) - { - buffer.Reverse(); - } - - return MemoryMarshal.Read(buffer); -#endif - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by two bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static ushort ReadUInt16BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[2]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt16BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by two bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static ushort ReadUInt16LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[2]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt16LittleEndian(buffer); - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by four bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static uint ReadUInt32BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt32BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static uint ReadUInt32LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[4]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt32LittleEndian(buffer); - } - - /// - /// Reads an from the current stream as big endian, and advances the stream position by eight bytes. - /// - /// The stream from which the value should be read. - /// The big endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static ulong ReadUInt64BigEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt64BigEndian(buffer); - } - - /// - /// Reads an from the current stream as little endian, and advances the stream position by eight - /// bytes. - /// - /// The stream from which the value should be read. - /// The little endian value. - /// is - /// does not support reading. - [CLSCompliant(false)] - public static ulong ReadUInt64LittleEndian(this Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanRead) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); - } - - Span buffer = stackalloc byte[8]; - _ = stream.Read(buffer); - return BinaryPrimitives.ReadUInt64LittleEndian(buffer); - } - /// /// Returns the hash of the current stream as an array of bytes using the specified hash algorithm. /// @@ -633,471 +115,4 @@ public static class StreamExtensions _ = stream.Read(buffer); // we don't care about the number of bytes read. we can ignore MustUseReturnValue return crypt.TryComputeHash(buffer, destination, out bytesWritten); } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by two bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, short value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[2]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, int value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by eight bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, long value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by two bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteBigEndian(this Stream stream, ushort value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[2]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteBigEndian(this Stream stream, uint value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as big endian, and advances the stream position by eight bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteBigEndian(this Stream stream, ulong value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, float value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by eight - /// bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, double value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by sixteen - /// bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteBigEndian(this Stream stream, decimal value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[16]; - value.TryWriteBigEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by two bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, short value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[2]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes an to the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, int value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by eight bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, long value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, float value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by eight - /// bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, double value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by sixteen - /// bytes. - /// - /// The stream to which the value should be written. - /// The to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - public static int WriteLittleEndian(this Stream stream, decimal value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[16]; - value.TryWriteLittleEndian(buffer); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by two bytes. - /// - /// The stream to which the value should be written. - /// The two-byte signed integer to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteLittleEndian(this Stream stream, ushort value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[2]; - BinaryPrimitives.WriteUInt16LittleEndian(buffer, value); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by four bytes. - /// - /// The stream to which the value should be written. - /// The two-byte signed integer to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteLittleEndian(this Stream stream, uint value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[4]; - BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); - return stream.WriteInternal(buffer); - } - - /// - /// Writes a to the current stream as little endian, and advances the stream position by eight bytes. - /// - /// The stream to which the value should be written. - /// The two-byte signed integer to write. - /// The number of bytes written to the stream. - /// is . - /// does not support writing. - [CLSCompliant(false)] - public static int WriteLittleEndian(this Stream stream, ulong value) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (!stream.CanWrite) - { - throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); - } - - Span buffer = stackalloc byte[8]; - BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); - return stream.WriteInternal(buffer); - } - - private static int WriteInternal(this Stream stream, ReadOnlySpan value) - { - long preWritePosition = stream.Position; - stream.Write(value); - return (int)(stream.Position - preWritePosition); - } }