diff --git a/Directory.Packages.props b/Directory.Packages.props index 6527647..68d31a0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,11 +11,11 @@ - + - + \ No newline at end of file diff --git a/PowerKit.Tests/Extensions/BinaryReaderExtensionsTests.cs b/PowerKit.Tests/Extensions/BinaryReaderExtensionsTests.cs index 9b4e11b..55ba24b 100644 --- a/PowerKit.Tests/Extensions/BinaryReaderExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/BinaryReaderExtensionsTests.cs @@ -141,4 +141,244 @@ public void SkipZeroes_AllZeroes_Test() // Assert stream.Position.Should().Be(3); } + + [Fact] + public void ReadInt16BigEndian_Test() + { + // Arrange + var data = new byte[] { 0x01, 0x02 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt16BigEndian(); + + // Assert + result.Should().Be(0x0102); + } + + [Fact] + public void ReadInt16LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0x02, 0x01 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt16LittleEndian(); + + // Assert + result.Should().Be(0x0102); + } + + [Fact] + public void ReadUInt16BigEndian_Test() + { + // Arrange + var data = new byte[] { 0xFF, 0xFE }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt16BigEndian(); + + // Assert + result.Should().Be((ushort)0xFFFE); + } + + [Fact] + public void ReadUInt16LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0xFE, 0xFF }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt16LittleEndian(); + + // Assert + result.Should().Be((ushort)0xFFFE); + } + + [Fact] + public void ReadInt32BigEndian_Test() + { + // Arrange + var data = new byte[] { 0x01, 0x02, 0x03, 0x04 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt32BigEndian(); + + // Assert + result.Should().Be(0x01020304); + } + + [Fact] + public void ReadInt32LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0x04, 0x03, 0x02, 0x01 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt32LittleEndian(); + + // Assert + result.Should().Be(0x01020304); + } + + [Fact] + public void ReadUInt32BigEndian_Test() + { + // Arrange + var data = new byte[] { 0xFF, 0xFE, 0xFD, 0xFC }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt32BigEndian(); + + // Assert + result.Should().Be(0xFFFEFDFCu); + } + + [Fact] + public void ReadUInt32LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0xFC, 0xFD, 0xFE, 0xFF }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt32LittleEndian(); + + // Assert + result.Should().Be(0xFFFEFDFCu); + } + + [Fact] + public void ReadInt64BigEndian_Test() + { + // Arrange + var data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt64BigEndian(); + + // Assert + result.Should().Be(0x0102030405060708L); + } + + [Fact] + public void ReadInt64LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadInt64LittleEndian(); + + // Assert + result.Should().Be(0x0102030405060708L); + } + + [Fact] + public void ReadUInt64BigEndian_Test() + { + // Arrange + var data = new byte[] { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt64BigEndian(); + + // Assert + result.Should().Be(0xFFFEFDFCFBFAF9F8uL); + } + + [Fact] + public void ReadUInt64LittleEndian_Test() + { + // Arrange + var data = new byte[] { 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadUInt64LittleEndian(); + + // Assert + result.Should().Be(0xFFFEFDFCFBFAF9F8uL); + } + + [Fact] + public void ReadSingleBigEndian_Test() + { + // Arrange — IEEE 754 big-endian bytes for 1.0f: 0x3F800000 + var data = new byte[] { 0x3F, 0x80, 0x00, 0x00 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadSingleBigEndian(); + + // Assert + result.Should().Be(1.0f); + } + + [Fact] + public void ReadSingleLittleEndian_Test() + { + // Arrange — IEEE 754 little-endian bytes for 1.0f: 0x3F800000 reversed + var data = new byte[] { 0x00, 0x00, 0x80, 0x3F }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadSingleLittleEndian(); + + // Assert + result.Should().Be(1.0f); + } + + [Fact] + public void ReadDoubleBigEndian_Test() + { + // Arrange — IEEE 754 big-endian bytes for 1.0d: 0x3FF0000000000000 + var data = new byte[] { 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadDoubleBigEndian(); + + // Assert + result.Should().Be(1.0d); + } + + [Fact] + public void ReadDoubleLittleEndian_Test() + { + // Arrange — IEEE 754 little-endian bytes for 1.0d: 0x3FF0000000000000 reversed + var data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F }; + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + // Act + var result = reader.ReadDoubleLittleEndian(); + + // Assert + result.Should().Be(1.0d); + } } diff --git a/PowerKit.Tests/Extensions/BinaryWriterExtensionsTests.cs b/PowerKit.Tests/Extensions/BinaryWriterExtensionsTests.cs index f277bb2..944eb5a 100644 --- a/PowerKit.Tests/Extensions/BinaryWriterExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/BinaryWriterExtensionsTests.cs @@ -67,4 +67,228 @@ public void WriteNullTerminatedString_Empty_Test() // Assert stream.ToArray().Should().Equal(0); } + + [Fact] + public void WriteBigEndian_Int16_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian((short)0x0102); + + // Assert + stream.ToArray().Should().Equal(0x01, 0x02); + } + + [Fact] + public void WriteBigEndian_UInt16_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian((ushort)0xFFFE); + + // Assert + stream.ToArray().Should().Equal(0xFF, 0xFE); + } + + [Fact] + public void WriteBigEndian_Int32_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(0x01020304); + + // Assert + stream.ToArray().Should().Equal(0x01, 0x02, 0x03, 0x04); + } + + [Fact] + public void WriteBigEndian_UInt32_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(0xFFFEFDFCu); + + // Assert + stream.ToArray().Should().Equal(0xFF, 0xFE, 0xFD, 0xFC); + } + + [Fact] + public void WriteBigEndian_Int64_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(0x0102030405060708L); + + // Assert + stream.ToArray().Should().Equal(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08); + } + + [Fact] + public void WriteBigEndian_UInt64_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(0xFFFEFDFCFBFAF9F8uL); + + // Assert + stream.ToArray().Should().Equal(0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8); + } + + [Fact] + public void WriteBigEndian_Single_Test() + { + // Arrange — IEEE 754 big-endian bytes for 1.0f: 0x3F800000 + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(1.0f); + + // Assert + stream.ToArray().Should().Equal(0x3F, 0x80, 0x00, 0x00); + } + + [Fact] + public void WriteBigEndian_Double_Test() + { + // Arrange — IEEE 754 big-endian bytes for 1.0d: 0x3FF0000000000000 + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteBigEndian(1.0d); + + // Assert + stream.ToArray().Should().Equal(0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + + [Fact] + public void WriteLittleEndian_Int16_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian((short)0x0102); + + // Assert + stream.ToArray().Should().Equal(0x02, 0x01); + } + + [Fact] + public void WriteLittleEndian_UInt16_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian((ushort)0xFFFE); + + // Assert + stream.ToArray().Should().Equal(0xFE, 0xFF); + } + + [Fact] + public void WriteLittleEndian_Int32_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(0x01020304); + + // Assert + stream.ToArray().Should().Equal(0x04, 0x03, 0x02, 0x01); + } + + [Fact] + public void WriteLittleEndian_UInt32_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(0xFFFEFDFCu); + + // Assert + stream.ToArray().Should().Equal(0xFC, 0xFD, 0xFE, 0xFF); + } + + [Fact] + public void WriteLittleEndian_Int64_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(0x0102030405060708L); + + // Assert + stream.ToArray().Should().Equal(0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01); + } + + [Fact] + public void WriteLittleEndian_UInt64_Test() + { + // Arrange + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(0xFFFEFDFCFBFAF9F8uL); + + // Assert + stream.ToArray().Should().Equal(0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF); + } + + [Fact] + public void WriteLittleEndian_Single_Test() + { + // Arrange — IEEE 754 little-endian bytes for 1.0f: 0x3F800000 reversed + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(1.0f); + + // Assert + stream.ToArray().Should().Equal(0x00, 0x00, 0x80, 0x3F); + } + + [Fact] + public void WriteLittleEndian_Double_Test() + { + // Arrange — IEEE 754 little-endian bytes for 1.0d: 0x3FF0000000000000 reversed + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + // Act + writer.WriteLittleEndian(1.0d); + + // Assert + stream.ToArray().Should().Equal(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F); + } } diff --git a/PowerKit/Extensions/BinaryReaderExtensions.cs b/PowerKit/Extensions/BinaryReaderExtensions.cs index 5899437..8d64226 100644 --- a/PowerKit/Extensions/BinaryReaderExtensions.cs +++ b/PowerKit/Extensions/BinaryReaderExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.IO; using System.Text; @@ -9,6 +10,15 @@ namespace PowerKit.Extensions; /// public static class BinaryReaderExtensions { + private static byte[] ReadExactBytes(BinaryReader reader, int count) + { + var bytes = reader.ReadBytes(count); + if (bytes.Length != count) + throw new EndOfStreamException(); + + return bytes; + } + extension(BinaryReader reader) { /// @@ -65,5 +75,101 @@ public void SkipZeroes(long? maxSkipLength = null) skipped++; } } + + /// + /// Reads a 2-byte signed integer from the stream using big-endian byte order. + /// + public short ReadInt16BigEndian() => + BinaryPrimitives.ReadInt16BigEndian(ReadExactBytes(reader, sizeof(short))); + + /// + /// Reads a 2-byte signed integer from the stream using little-endian byte order. + /// + public short ReadInt16LittleEndian() => + BinaryPrimitives.ReadInt16LittleEndian(ReadExactBytes(reader, sizeof(short))); + + /// + /// Reads a 2-byte unsigned integer from the stream using big-endian byte order. + /// + public ushort ReadUInt16BigEndian() => + BinaryPrimitives.ReadUInt16BigEndian(ReadExactBytes(reader, sizeof(ushort))); + + /// + /// Reads a 2-byte unsigned integer from the stream using little-endian byte order. + /// + public ushort ReadUInt16LittleEndian() => + BinaryPrimitives.ReadUInt16LittleEndian(ReadExactBytes(reader, sizeof(ushort))); + + /// + /// Reads a 4-byte signed integer from the stream using big-endian byte order. + /// + public int ReadInt32BigEndian() => + BinaryPrimitives.ReadInt32BigEndian(ReadExactBytes(reader, sizeof(int))); + + /// + /// Reads a 4-byte signed integer from the stream using little-endian byte order. + /// + public int ReadInt32LittleEndian() => + BinaryPrimitives.ReadInt32LittleEndian(ReadExactBytes(reader, sizeof(int))); + + /// + /// Reads a 4-byte unsigned integer from the stream using big-endian byte order. + /// + public uint ReadUInt32BigEndian() => + BinaryPrimitives.ReadUInt32BigEndian(ReadExactBytes(reader, sizeof(uint))); + + /// + /// Reads a 4-byte unsigned integer from the stream using little-endian byte order. + /// + public uint ReadUInt32LittleEndian() => + BinaryPrimitives.ReadUInt32LittleEndian(ReadExactBytes(reader, sizeof(uint))); + + /// + /// Reads an 8-byte signed integer from the stream using big-endian byte order. + /// + public long ReadInt64BigEndian() => + BinaryPrimitives.ReadInt64BigEndian(ReadExactBytes(reader, sizeof(long))); + + /// + /// Reads an 8-byte signed integer from the stream using little-endian byte order. + /// + public long ReadInt64LittleEndian() => + BinaryPrimitives.ReadInt64LittleEndian(ReadExactBytes(reader, sizeof(long))); + + /// + /// Reads an 8-byte unsigned integer from the stream using big-endian byte order. + /// + public ulong ReadUInt64BigEndian() => + BinaryPrimitives.ReadUInt64BigEndian(ReadExactBytes(reader, sizeof(ulong))); + + /// + /// Reads an 8-byte unsigned integer from the stream using little-endian byte order. + /// + public ulong ReadUInt64LittleEndian() => + BinaryPrimitives.ReadUInt64LittleEndian(ReadExactBytes(reader, sizeof(ulong))); + + /// + /// Reads a 4-byte floating-point value from the stream using big-endian byte order. + /// + public float ReadSingleBigEndian() => + BinaryPrimitives.ReadSingleBigEndian(ReadExactBytes(reader, sizeof(float))); + + /// + /// Reads a 4-byte floating-point value from the stream using little-endian byte order. + /// + public float ReadSingleLittleEndian() => + BinaryPrimitives.ReadSingleLittleEndian(ReadExactBytes(reader, sizeof(float))); + + /// + /// Reads an 8-byte floating-point value from the stream using big-endian byte order. + /// + public double ReadDoubleBigEndian() => + BinaryPrimitives.ReadDoubleBigEndian(ReadExactBytes(reader, sizeof(double))); + + /// + /// Reads an 8-byte floating-point value from the stream using little-endian byte order. + /// + public double ReadDoubleLittleEndian() => + BinaryPrimitives.ReadDoubleLittleEndian(ReadExactBytes(reader, sizeof(double))); } } diff --git a/PowerKit/Extensions/BinaryWriterExtensions.cs b/PowerKit/Extensions/BinaryWriterExtensions.cs index 9fa950e..0cf438d 100644 --- a/PowerKit/Extensions/BinaryWriterExtensions.cs +++ b/PowerKit/Extensions/BinaryWriterExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.IO; namespace PowerKit.Extensions; @@ -36,5 +37,165 @@ public void WriteNullTerminatedString(string value) writer.Write('\0'); } + + /// + /// Writes a 2-byte signed integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(short value) + { + var buffer = new byte[sizeof(short)]; + BinaryPrimitives.WriteInt16BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 2-byte unsigned integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(ushort value) + { + var buffer = new byte[sizeof(ushort)]; + BinaryPrimitives.WriteUInt16BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte signed integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(int value) + { + var buffer = new byte[sizeof(int)]; + BinaryPrimitives.WriteInt32BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte unsigned integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(uint value) + { + var buffer = new byte[sizeof(uint)]; + BinaryPrimitives.WriteUInt32BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte signed integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(long value) + { + var buffer = new byte[sizeof(long)]; + BinaryPrimitives.WriteInt64BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte unsigned integer to the stream using big-endian byte order. + /// + public void WriteBigEndian(ulong value) + { + var buffer = new byte[sizeof(ulong)]; + BinaryPrimitives.WriteUInt64BigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte floating-point value to the stream using big-endian byte order. + /// + public void WriteBigEndian(float value) + { + var buffer = new byte[sizeof(float)]; + BinaryPrimitives.WriteSingleBigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte floating-point value to the stream using big-endian byte order. + /// + public void WriteBigEndian(double value) + { + var buffer = new byte[sizeof(double)]; + BinaryPrimitives.WriteDoubleBigEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 2-byte signed integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(short value) + { + var buffer = new byte[sizeof(short)]; + BinaryPrimitives.WriteInt16LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 2-byte unsigned integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(ushort value) + { + var buffer = new byte[sizeof(ushort)]; + BinaryPrimitives.WriteUInt16LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte signed integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(int value) + { + var buffer = new byte[sizeof(int)]; + BinaryPrimitives.WriteInt32LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte unsigned integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(uint value) + { + var buffer = new byte[sizeof(uint)]; + BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte signed integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(long value) + { + var buffer = new byte[sizeof(long)]; + BinaryPrimitives.WriteInt64LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte unsigned integer to the stream using little-endian byte order. + /// + public void WriteLittleEndian(ulong value) + { + var buffer = new byte[sizeof(ulong)]; + BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes a 4-byte floating-point value to the stream using little-endian byte order. + /// + public void WriteLittleEndian(float value) + { + var buffer = new byte[sizeof(float)]; + BinaryPrimitives.WriteSingleLittleEndian(buffer, value); + writer.Write(buffer); + } + + /// + /// Writes an 8-byte floating-point value to the stream using little-endian byte order. + /// + public void WriteLittleEndian(double value) + { + var buffer = new byte[sizeof(double)]; + BinaryPrimitives.WriteDoubleLittleEndian(buffer, value); + writer.Write(buffer); + } } }