diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 9f998a0afe9ef..32e28be4e9d2f 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -438,6 +438,10 @@ public static partial class BinaryPrimitives public static int ReadInt32LittleEndian(System.ReadOnlySpan source) { throw null; } public static long ReadInt64BigEndian(System.ReadOnlySpan source) { throw null; } public static long ReadInt64LittleEndian(System.ReadOnlySpan source) { throw null; } + public static System.Int128 ReadInt128BigEndian(System.ReadOnlySpan source) { throw null; } + public static System.Int128 ReadInt128LittleEndian(System.ReadOnlySpan source) { throw null; } + public static nint ReadIntPtrBigEndian(System.ReadOnlySpan source) { throw null; } + public static nint ReadIntPtrLittleEndian(System.ReadOnlySpan source) { throw null; } public static float ReadSingleBigEndian(System.ReadOnlySpan source) { throw null; } public static float ReadSingleLittleEndian(System.ReadOnlySpan source) { throw null; } [System.CLSCompliantAttribute(false)] @@ -452,6 +456,14 @@ public static partial class BinaryPrimitives public static ulong ReadUInt64BigEndian(System.ReadOnlySpan source) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong ReadUInt64LittleEndian(System.ReadOnlySpan source) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.UInt128 ReadUInt128BigEndian(System.ReadOnlySpan source) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.UInt128 ReadUInt128LittleEndian(System.ReadOnlySpan source) { throw null; } + [System.CLSCompliantAttribute(false)] + public static nuint ReadUIntPtrBigEndian(System.ReadOnlySpan source) { throw null; } + [System.CLSCompliantAttribute(false)] + public static nuint ReadUIntPtrLittleEndian(System.ReadOnlySpan source) { throw null; } public static byte ReverseEndianness(byte value) { throw null; } public static short ReverseEndianness(short value) { throw null; } public static int ReverseEndianness(int value) { throw null; } @@ -495,6 +507,10 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryReadInt32LittleEndian(System.ReadOnlySpan source, out int value) { throw null; } public static bool TryReadInt64BigEndian(System.ReadOnlySpan source, out long value) { throw null; } public static bool TryReadInt64LittleEndian(System.ReadOnlySpan source, out long value) { throw null; } + public static bool TryReadInt128BigEndian(System.ReadOnlySpan source, out System.Int128 value) { throw null; } + public static bool TryReadInt128LittleEndian(System.ReadOnlySpan source, out System.Int128 value) { throw null; } + public static bool TryReadIntPtrBigEndian(System.ReadOnlySpan source, out nint value) { throw null; } + public static bool TryReadIntPtrLittleEndian(System.ReadOnlySpan source, out nint value) { throw null; } public static bool TryReadSingleBigEndian(System.ReadOnlySpan source, out float value) { throw null; } public static bool TryReadSingleLittleEndian(System.ReadOnlySpan source, out float value) { throw null; } [System.CLSCompliantAttribute(false)] @@ -509,6 +525,14 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryReadUInt64BigEndian(System.ReadOnlySpan source, out ulong value) { throw null; } [System.CLSCompliantAttribute(false)] public static bool TryReadUInt64LittleEndian(System.ReadOnlySpan source, out ulong value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryReadUInt128BigEndian(System.ReadOnlySpan source, out System.UInt128 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryReadUInt128LittleEndian(System.ReadOnlySpan source, out System.UInt128 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryReadUIntPtrBigEndian(System.ReadOnlySpan source, out nuint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryReadUIntPtrLittleEndian(System.ReadOnlySpan source, out nuint value) { throw null; } public static bool TryWriteDoubleBigEndian(System.Span destination, double value) { throw null; } public static bool TryWriteDoubleLittleEndian(System.Span destination, double value) { throw null; } public static bool TryWriteHalfBigEndian(System.Span destination, System.Half value) { throw null; } @@ -519,6 +543,10 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryWriteInt32LittleEndian(System.Span destination, int value) { throw null; } public static bool TryWriteInt64BigEndian(System.Span destination, long value) { throw null; } public static bool TryWriteInt64LittleEndian(System.Span destination, long value) { throw null; } + public static bool TryWriteInt128BigEndian(System.Span destination, System.Int128 value) { throw null; } + public static bool TryWriteInt128LittleEndian(System.Span destination, System.Int128 value) { throw null; } + public static bool TryWriteIntPtrBigEndian(System.Span destination, nint value) { throw null; } + public static bool TryWriteIntPtrLittleEndian(System.Span destination, nint value) { throw null; } public static bool TryWriteSingleBigEndian(System.Span destination, float value) { throw null; } public static bool TryWriteSingleLittleEndian(System.Span destination, float value) { throw null; } [System.CLSCompliantAttribute(false)] @@ -533,6 +561,14 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryWriteUInt64BigEndian(System.Span destination, ulong value) { throw null; } [System.CLSCompliantAttribute(false)] public static bool TryWriteUInt64LittleEndian(System.Span destination, ulong value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryWriteUInt128BigEndian(System.Span destination, System.UInt128 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryWriteUInt128LittleEndian(System.Span destination, System.UInt128 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryWriteUIntPtrBigEndian(System.Span destination, nuint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static bool TryWriteUIntPtrLittleEndian(System.Span destination, nuint value) { throw null; } public static void WriteDoubleBigEndian(System.Span destination, double value) { } public static void WriteDoubleLittleEndian(System.Span destination, double value) { } public static void WriteHalfBigEndian(System.Span destination, System.Half value) { } @@ -543,6 +579,10 @@ public static void WriteInt32BigEndian(System.Span destination, int value) public static void WriteInt32LittleEndian(System.Span destination, int value) { } public static void WriteInt64BigEndian(System.Span destination, long value) { } public static void WriteInt64LittleEndian(System.Span destination, long value) { } + public static void WriteInt128BigEndian(System.Span destination, System.Int128 value) { } + public static void WriteInt128LittleEndian(System.Span destination, System.Int128 value) { } + public static void WriteIntPtrBigEndian(System.Span destination, nint value) { } + public static void WriteIntPtrLittleEndian(System.Span destination, nint value) { } public static void WriteSingleBigEndian(System.Span destination, float value) { } public static void WriteSingleLittleEndian(System.Span destination, float value) { } [System.CLSCompliantAttribute(false)] @@ -557,6 +597,14 @@ public static void WriteUInt32LittleEndian(System.Span destination, uint v public static void WriteUInt64BigEndian(System.Span destination, ulong value) { } [System.CLSCompliantAttribute(false)] public static void WriteUInt64LittleEndian(System.Span destination, ulong value) { } + [System.CLSCompliantAttribute(false)] + public static void WriteUInt128BigEndian(System.Span destination, System.UInt128 value) { } + [System.CLSCompliantAttribute(false)] + public static void WriteUInt128LittleEndian(System.Span destination, System.UInt128 value) { } + [System.CLSCompliantAttribute(false)] + public static void WriteUIntPtrBigEndian(System.Span destination, nuint value) { } + [System.CLSCompliantAttribute(false)] + public static void WriteUIntPtrLittleEndian(System.Span destination, nuint value) { } } } namespace System.Buffers.Text diff --git a/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs b/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs index b4fb102bb1e6d..8f3f01c7105d6 100644 --- a/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs +++ b/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs @@ -14,19 +14,21 @@ public class BinaryReaderUnitTests [Fact] public void SpanRead() { - ulong value; // [11 22 33 44 55 66 77 88] + UInt128 value; // [11 22 33 44 55 66 77 88, 99 AA BB CC DD EE FF 00] + if (BitConverter.IsLittleEndian) { - value = 0x8877665544332211; + value = new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211); } else { - value = 0x1122334455667788; + value = new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00); } + Span span; unsafe { - span = new Span(&value, 8); + span = new Span(&value, sizeof(UInt128)); } Assert.Equal(0x11, MemoryMarshal.Read(span)); @@ -85,6 +87,59 @@ public void SpanRead() Assert.True(TryReadInt64LittleEndian(span, out longValue)); Assert.Equal(unchecked((long)0x8877665544332211), longValue); + if (Environment.Is64BitProcess) + { + Assert.Equal(unchecked((nuint)0x1122334455667788), ReadUIntPtrBigEndian(span)); + Assert.True(TryReadUIntPtrBigEndian(span, out nuint nuintValue)); + Assert.Equal(unchecked((nuint)0x1122334455667788), nuintValue); + + Assert.Equal(unchecked((nuint)0x8877665544332211), ReadUIntPtrLittleEndian(span)); + Assert.True(TryReadUIntPtrLittleEndian(span, out nuintValue)); + Assert.Equal(unchecked((nuint)0x8877665544332211), nuintValue); + + Assert.Equal(unchecked((nint)0x1122334455667788), ReadIntPtrBigEndian(span)); + Assert.True(TryReadIntPtrBigEndian(span, out nint nintValue)); + Assert.Equal(unchecked((nint)0x1122334455667788), nintValue); + + Assert.Equal(unchecked((nint)0x8877665544332211), ReadIntPtrLittleEndian(span)); + Assert.True(TryReadIntPtrLittleEndian(span, out nintValue)); + Assert.Equal(unchecked((nint)0x8877665544332211), nintValue); + } + else + { + Assert.Equal(0x11223344, ReadUIntPtrBigEndian(span)); + Assert.True(TryReadUIntPtrBigEndian(span, out nuint nuintValue)); + Assert.Equal(0x11223344, nuintValue); + + Assert.Equal(0x44332211, ReadUIntPtrLittleEndian(span)); + Assert.True(TryReadUIntPtrLittleEndian(span, out nuintValue)); + Assert.Equal(0x44332211, nuintValue); + + Assert.Equal(0x11223344, ReadIntPtrBigEndian(span)); + Assert.True(TryReadIntPtrBigEndian(span, out nint nintValue)); + Assert.Equal(0x11223344, nintValue); + + Assert.Equal(0x44332211, ReadIntPtrLittleEndian(span)); + Assert.True(TryReadIntPtrLittleEndian(span, out nintValue)); + Assert.Equal(0x44332211, nintValue); + } + + Assert.Equal(new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00), ReadUInt128BigEndian(span)); + Assert.True(TryReadUInt128BigEndian(span, out UInt128 uint128Value)); + Assert.Equal(new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00), uint128Value); + + Assert.Equal(new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211), ReadUInt128LittleEndian(span)); + Assert.True(TryReadUInt128LittleEndian(span, out uint128Value)); + Assert.Equal(new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211), uint128Value); + + Assert.Equal(new Int128(0x1122334455667788, 0x99AABBCCDDEEFF00), ReadInt128BigEndian(span)); + Assert.True(TryReadInt128BigEndian(span, out Int128 int128Value)); + Assert.Equal(new Int128(0x1122334455667788, 0x99AABBCCDDEEFF00), int128Value); + + Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), ReadInt128LittleEndian(span)); + Assert.True(TryReadInt128LittleEndian(span, out int128Value)); + Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), int128Value); + Half expectedHalf = BitConverter.Int16BitsToHalf(0x1122); Assert.Equal(expectedHalf, ReadHalfBigEndian(span)); Assert.True(TryReadHalfBigEndian(span, out Half halfValue)); @@ -119,19 +174,21 @@ public void SpanRead() [Fact] public void ReadOnlySpanRead() { - ulong value; // [11 22 33 44 55 66 77 88] + UInt128 value; // [11 22 33 44 55 66 77 88, 99 AA BB CC DD EE FF 00] + if (BitConverter.IsLittleEndian) { - value = 0x8877665544332211; + value = new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211); } else { - value = 0x1122334455667788; + value = new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00); } + ReadOnlySpan span; unsafe { - span = new ReadOnlySpan(&value, 8); + span = new ReadOnlySpan(&value, sizeof(UInt128)); } Assert.Equal(0x11, MemoryMarshal.Read(span)); @@ -190,6 +247,59 @@ public void ReadOnlySpanRead() Assert.True(TryReadInt64LittleEndian(span, out longValue)); Assert.Equal(unchecked((long)0x8877665544332211), longValue); + if (Environment.Is64BitProcess) + { + Assert.Equal(unchecked((nuint)0x1122334455667788), ReadUIntPtrBigEndian(span)); + Assert.True(TryReadUIntPtrBigEndian(span, out nuint nuintValue)); + Assert.Equal(unchecked((nuint)(0x1122334455667788)), nuintValue); + + Assert.Equal(unchecked((nuint)0x8877665544332211), ReadUIntPtrLittleEndian(span)); + Assert.True(TryReadUIntPtrLittleEndian(span, out nuintValue)); + Assert.Equal(unchecked((nuint)0x8877665544332211), nuintValue); + + Assert.Equal(unchecked((nint)0x1122334455667788), ReadIntPtrBigEndian(span)); + Assert.True(TryReadIntPtrBigEndian(span, out nint nintValue)); + Assert.Equal(unchecked((nint)0x1122334455667788), nintValue); + + Assert.Equal(unchecked((nint)0x8877665544332211), ReadIntPtrLittleEndian(span)); + Assert.True(TryReadIntPtrLittleEndian(span, out nintValue)); + Assert.Equal(unchecked((nint)0x8877665544332211), nintValue); + } + else + { + Assert.Equal(0x11223344, ReadUIntPtrBigEndian(span)); + Assert.True(TryReadUIntPtrBigEndian(span, out nuint nuintValue)); + Assert.Equal(0x11223344, nuintValue); + + Assert.Equal(0x44332211, ReadUIntPtrLittleEndian(span)); + Assert.True(TryReadUIntPtrLittleEndian(span, out nuintValue)); + Assert.Equal(0x44332211, nuintValue); + + Assert.Equal(0x11223344, ReadIntPtrBigEndian(span)); + Assert.True(TryReadIntPtrBigEndian(span, out nint nintValue)); + Assert.Equal(0x11223344, nintValue); + + Assert.Equal(0x44332211, ReadIntPtrLittleEndian(span)); + Assert.True(TryReadIntPtrLittleEndian(span, out nintValue)); + Assert.Equal(0x44332211, nintValue); + } + + Assert.Equal(new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00), ReadUInt128BigEndian(span)); + Assert.True(TryReadUInt128BigEndian(span, out UInt128 uint128Value)); + Assert.Equal(new UInt128(0x1122334455667788, 0x99AABBCCDDEEFF00), uint128Value); + + Assert.Equal(new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211), ReadUInt128LittleEndian(span)); + Assert.True(TryReadUInt128LittleEndian(span, out uint128Value)); + Assert.Equal(new UInt128(0x00FFEEDDCCBBAA99, 0x8877665544332211), uint128Value); + + Assert.Equal(new Int128(0x1122334455667788, 0x99AABBCCDDEEFF00), ReadInt128BigEndian(span)); + Assert.True(TryReadInt128BigEndian(span, out Int128 int128Value)); + Assert.Equal(new Int128(0x1122334455667788, 0x99AABBCCDDEEFF00), int128Value); + + Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), ReadInt128LittleEndian(span)); + Assert.True(TryReadInt128LittleEndian(span, out int128Value)); + Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), int128Value); + Half expectedHalf = BitConverter.Int16BitsToHalf(0x1122); Assert.Equal(expectedHalf, ReadHalfBigEndian(span)); Assert.True(TryReadHalfBigEndian(span, out Half halfValue)); @@ -236,6 +346,10 @@ public void SpanReadFail() Assert.False(MemoryMarshal.TryRead(span, out int intValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out long longValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out nint nintValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out Int128 int128Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out ushort ushortValue)); @@ -243,6 +357,10 @@ public void SpanReadFail() Assert.False(MemoryMarshal.TryRead(span, out uint uintValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out ulong ulongValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out nuint nuintValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out UInt128 uint128Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out Half halfValue)); @@ -271,6 +389,10 @@ public void ReadOnlySpanReadFail() Assert.False(MemoryMarshal.TryRead(span, out int intValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out long longValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out nint nintValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out Int128 int128Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out ushort ushortValue)); @@ -278,6 +400,10 @@ public void ReadOnlySpanReadFail() Assert.False(MemoryMarshal.TryRead(span, out uint uintValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out ulong ulongValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out nuint nuintValue)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out UInt128 uint128Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out Half halfValue)); @@ -314,6 +440,25 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() WriteDoubleBigEndian(spanBE.Slice(72), s_testStruct.D1); WriteHalfBigEndian(spanBE.Slice(80), s_testStruct.H0); WriteHalfBigEndian(spanBE.Slice(82), s_testStruct.H1); + WriteInt128BigEndian(spanBE.Slice(84), s_testStruct.I128_0); + WriteInt128BigEndian(spanBE.Slice(100), s_testStruct.I128_1); + WriteUInt128BigEndian(spanBE.Slice(116), s_testStruct.U128_0); + WriteUInt128BigEndian(spanBE.Slice(132), s_testStruct.U128_1); + + if (Environment.Is64BitProcess) + { + WriteIntPtrBigEndian(spanBE.Slice(148), s_testStruct.N0); + WriteIntPtrBigEndian(spanBE.Slice(156), s_testStruct.N1); + WriteUIntPtrBigEndian(spanBE.Slice(164), s_testStruct.UN0); + WriteUIntPtrBigEndian(spanBE.Slice(172), s_testStruct.UN1); + } + else + { + WriteIntPtrBigEndian(spanBE.Slice(148), s_testStruct.N0); + WriteIntPtrBigEndian(spanBE.Slice(152), s_testStruct.N1); + WriteUIntPtrBigEndian(spanBE.Slice(156), s_testStruct.UN0); + WriteUIntPtrBigEndian(spanBE.Slice(160), s_testStruct.UN1); + } ReadOnlySpan readOnlySpanBE = new ReadOnlySpan(spanBE.ToArray()); @@ -336,9 +481,28 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() F1 = ReadSingleBigEndian(spanBE.Slice(68)), D1 = ReadDoubleBigEndian(spanBE.Slice(72)), H0 = ReadHalfBigEndian(spanBE.Slice(80)), - H1 = ReadHalfBigEndian(spanBE.Slice(82)) + H1 = ReadHalfBigEndian(spanBE.Slice(82)), + I128_0 = ReadInt128BigEndian(spanBE.Slice(84)), + I128_1 = ReadInt128BigEndian(spanBE.Slice(100)), + U128_0 = ReadUInt128BigEndian(spanBE.Slice(116)), + U128_1 = ReadUInt128BigEndian(spanBE.Slice(132)), }; + if (Environment.Is64BitProcess) + { + readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(148)); + readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(156)); + readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(164)); + readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(172)); + } + else + { + readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(148)); + readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(152)); + readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(156)); + readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(160)); + } + var readStructFromReadOnlySpan = new TestStruct { S0 = ReadInt16BigEndian(readOnlySpanBE), @@ -358,9 +522,28 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() F1 = ReadSingleBigEndian(readOnlySpanBE.Slice(68)), D1 = ReadDoubleBigEndian(readOnlySpanBE.Slice(72)), H0 = ReadHalfBigEndian(readOnlySpanBE.Slice(80)), - H1 = ReadHalfBigEndian(readOnlySpanBE.Slice(82)) + H1 = ReadHalfBigEndian(readOnlySpanBE.Slice(82)), + I128_0 = ReadInt128BigEndian(readOnlySpanBE.Slice(84)), + I128_1 = ReadInt128BigEndian(readOnlySpanBE.Slice(100)), + U128_0 = ReadUInt128BigEndian(readOnlySpanBE.Slice(116)), + U128_1 = ReadUInt128BigEndian(readOnlySpanBE.Slice(132)), }; + if (Environment.Is64BitProcess) + { + readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(148)); + readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(156)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(164)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(172)); + } + else + { + readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(148)); + readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(152)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(156)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(160)); + } + Assert.Equal(s_testStruct, readStruct); Assert.Equal(s_testStruct, readStructFromReadOnlySpan); } @@ -388,6 +571,25 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() WriteDoubleLittleEndian(spanLE.Slice(72), s_testStruct.D1); WriteHalfLittleEndian(spanLE.Slice(80), s_testStruct.H0); WriteHalfLittleEndian(spanLE.Slice(82), s_testStruct.H1); + WriteInt128LittleEndian(spanLE.Slice(84), s_testStruct.I128_0); + WriteInt128LittleEndian(spanLE.Slice(100), s_testStruct.I128_1); + WriteUInt128LittleEndian(spanLE.Slice(116), s_testStruct.U128_0); + WriteUInt128LittleEndian(spanLE.Slice(132), s_testStruct.U128_1); + + if (Environment.Is64BitProcess) + { + WriteIntPtrLittleEndian(spanLE.Slice(148), s_testStruct.N0); + WriteIntPtrLittleEndian(spanLE.Slice(156), s_testStruct.N1); + WriteUIntPtrLittleEndian(spanLE.Slice(164), s_testStruct.UN0); + WriteUIntPtrLittleEndian(spanLE.Slice(172), s_testStruct.UN1); + } + else + { + WriteIntPtrLittleEndian(spanLE.Slice(148), s_testStruct.N0); + WriteIntPtrLittleEndian(spanLE.Slice(152), s_testStruct.N1); + WriteUIntPtrLittleEndian(spanLE.Slice(156), s_testStruct.UN0); + WriteUIntPtrLittleEndian(spanLE.Slice(160), s_testStruct.UN1); + } ReadOnlySpan readOnlySpanLE = new ReadOnlySpan(spanLE.ToArray()); @@ -410,9 +612,28 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() F1 = ReadSingleLittleEndian(spanLE.Slice(68)), D1 = ReadDoubleLittleEndian(spanLE.Slice(72)), H0 = ReadHalfLittleEndian(spanLE.Slice(80)), - H1 = ReadHalfLittleEndian(spanLE.Slice(82)) + H1 = ReadHalfLittleEndian(spanLE.Slice(82)), + I128_0 = ReadInt128LittleEndian(spanLE.Slice(84)), + I128_1 = ReadInt128LittleEndian(spanLE.Slice(100)), + U128_0 = ReadUInt128LittleEndian(spanLE.Slice(116)), + U128_1 = ReadUInt128LittleEndian(spanLE.Slice(132)), }; + if (Environment.Is64BitProcess) + { + readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(148)); + readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(156)); + readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(164)); + readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(172)); + } + else + { + readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(148)); + readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(152)); + readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(156)); + readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(160)); + } + var readStructFromReadOnlySpan = new TestStruct { S0 = ReadInt16LittleEndian(readOnlySpanLE), @@ -432,9 +653,28 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() F1 = ReadSingleLittleEndian(readOnlySpanLE.Slice(68)), D1 = ReadDoubleLittleEndian(readOnlySpanLE.Slice(72)), H0 = ReadHalfLittleEndian(readOnlySpanLE.Slice(80)), - H1 = ReadHalfLittleEndian(readOnlySpanLE.Slice(82)) + H1 = ReadHalfLittleEndian(readOnlySpanLE.Slice(82)), + I128_0 = ReadInt128LittleEndian(readOnlySpanLE.Slice(84)), + I128_1 = ReadInt128LittleEndian(readOnlySpanLE.Slice(100)), + U128_0 = ReadUInt128LittleEndian(readOnlySpanLE.Slice(116)), + U128_1 = ReadUInt128LittleEndian(readOnlySpanLE.Slice(132)), }; + if (Environment.Is64BitProcess) + { + readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(148)); + readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(156)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(164)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(172)); + } + else + { + readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(148)); + readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(152)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(156)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(160)); + } + Assert.Equal(s_testStruct, readStruct); Assert.Equal(s_testStruct, readStructFromReadOnlySpan); } @@ -570,6 +810,14 @@ public void ReadingStructFieldByFieldOrReadAndReverseEndianness() D1 = double.MinValue, H0 = Half.MaxValue, H1 = Half.MinValue, + I128_0 = Int128.MaxValue, + I128_1 = Int128.MinValue, + U128_1 = UInt128.MinValue, + U128_0 = UIntPtr.MaxValue, + N0 = nint.MaxValue, + N1 = nint.MinValue, + UN1 = nuint.MinValue, + UN0 = nuint.MaxValue, }; [StructLayout(LayoutKind.Sequential)] @@ -593,6 +841,14 @@ private struct TestStruct public double D1; public Half H0; public Half H1; + public Int128 I128_0; + public Int128 I128_1; + public UInt128 U128_1; + public UInt128 U128_0; + public nint N0; + public nint N1; + public nuint UN1; + public nuint UN0; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs index 93e40c52f7359..07e961d22b0c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs @@ -43,7 +43,7 @@ public static Half ReadHalfBigEndian(ReadOnlySpan source) } /// - /// Reads an Int16 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ReadInt16BigEndian(ReadOnlySpan source) @@ -54,7 +54,7 @@ public static short ReadInt16BigEndian(ReadOnlySpan source) } /// - /// Reads an Int32 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ReadInt32BigEndian(ReadOnlySpan source) @@ -65,7 +65,7 @@ public static int ReadInt32BigEndian(ReadOnlySpan source) } /// - /// Reads an Int64 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long ReadInt64BigEndian(ReadOnlySpan source) @@ -75,6 +75,28 @@ public static long ReadInt64BigEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Int128 ReadInt128BigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint ReadIntPtrBigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as big endian. /// @@ -93,7 +115,7 @@ public static float ReadSingleBigEndian(ReadOnlySpan source) } /// - /// Reads a UInt16 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -105,7 +127,7 @@ public static ushort ReadUInt16BigEndian(ReadOnlySpan source) } /// - /// Reads a UInt32 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -117,7 +139,7 @@ public static uint ReadUInt32BigEndian(ReadOnlySpan source) } /// - /// Reads a UInt64 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -128,6 +150,30 @@ public static ulong ReadUInt64BigEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static UInt128 ReadUInt128BigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint ReadUIntPtrBigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as big endian. /// @@ -173,9 +219,9 @@ public static bool TryReadHalfBigEndian(ReadOnlySpan source, out Half valu } /// - /// Reads an Int16 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain an Int16, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt16BigEndian(ReadOnlySpan source, out short value) { @@ -190,9 +236,9 @@ public static bool TryReadInt16BigEndian(ReadOnlySpan source, out short va } /// - /// Reads an Int32 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain an Int32, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt32BigEndian(ReadOnlySpan source, out int value) { @@ -207,9 +253,9 @@ public static bool TryReadInt32BigEndian(ReadOnlySpan source, out int valu } /// - /// Reads an Int64 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain an Int64, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt64BigEndian(ReadOnlySpan source, out long value) { @@ -223,6 +269,40 @@ public static bool TryReadInt64BigEndian(ReadOnlySpan source, out long val return MemoryMarshal.TryRead(source, out value); } + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// If the span is too small to contain a , return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadInt128BigEndian(ReadOnlySpan source, out Int128 value) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out Int128 tmp); + value = ReverseEndianness(tmp); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// If the span is too small to contain a , return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadIntPtrBigEndian(ReadOnlySpan source, out nint value) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out nint tmp); + value = ReverseEndianness(tmp); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + /// /// Reads a from the beginning of a read-only span of bytes, as big endian. /// @@ -245,9 +325,9 @@ public static bool TryReadSingleBigEndian(ReadOnlySpan source, out float v } /// - /// Reads a UInt16 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain a UInt16, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt16BigEndian(ReadOnlySpan source, out ushort value) @@ -263,9 +343,9 @@ public static bool TryReadUInt16BigEndian(ReadOnlySpan source, out ushort } /// - /// Reads a UInt32 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain a UInt32, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt32BigEndian(ReadOnlySpan source, out uint value) @@ -281,9 +361,9 @@ public static bool TryReadUInt32BigEndian(ReadOnlySpan source, out uint va } /// - /// Reads a UInt64 out of a read-only span of bytes as big endian. + /// Reads a from the beginning of a read-only span of bytes, as big endian. /// - /// If the span is too small to contain a UInt64, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt64BigEndian(ReadOnlySpan source, out ulong value) @@ -297,5 +377,41 @@ public static bool TryReadUInt64BigEndian(ReadOnlySpan source, out ulong v return MemoryMarshal.TryRead(source, out value); } + + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// If the span is too small to contain a , return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadUInt128BigEndian(ReadOnlySpan source, out UInt128 value) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out UInt128 tmp); + value = ReverseEndianness(tmp); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// If the span is too small to contain a , return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadUIntPtrBigEndian(ReadOnlySpan source, out nuint value) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out nuint tmp); + value = ReverseEndianness(tmp); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs index 2115eec5c381c..8c9df7eef8692 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs @@ -43,7 +43,7 @@ public static Half ReadHalfLittleEndian(ReadOnlySpan source) } /// - /// Reads an Int16 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ReadInt16LittleEndian(ReadOnlySpan source) @@ -54,7 +54,7 @@ public static short ReadInt16LittleEndian(ReadOnlySpan source) } /// - /// Reads an Int32 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ReadInt32LittleEndian(ReadOnlySpan source) @@ -65,7 +65,7 @@ public static int ReadInt32LittleEndian(ReadOnlySpan source) } /// - /// Reads an Int64 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long ReadInt64LittleEndian(ReadOnlySpan source) @@ -75,6 +75,28 @@ public static long ReadInt64LittleEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Int128 ReadInt128LittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint ReadIntPtrLittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as little endian. /// @@ -93,7 +115,7 @@ public static float ReadSingleLittleEndian(ReadOnlySpan source) } /// - /// Reads a UInt16 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -105,7 +127,7 @@ public static ushort ReadUInt16LittleEndian(ReadOnlySpan source) } /// - /// Reads a UInt32 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -117,7 +139,7 @@ public static uint ReadUInt32LittleEndian(ReadOnlySpan source) } /// - /// Reads a UInt64 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -128,6 +150,30 @@ public static ulong ReadUInt64LittleEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static UInt128 ReadUInt128LittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint ReadUIntPtrLittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + ReverseEndianness(MemoryMarshal.Read(source)) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as little endian. /// @@ -173,9 +219,9 @@ public static bool TryReadHalfLittleEndian(ReadOnlySpan source, out Half v } /// - /// Reads an Int16 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain an Int16, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt16LittleEndian(ReadOnlySpan source, out short value) { @@ -190,9 +236,9 @@ public static bool TryReadInt16LittleEndian(ReadOnlySpan source, out short } /// - /// Reads an Int32 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain an Int32, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt32LittleEndian(ReadOnlySpan source, out int value) { @@ -207,9 +253,9 @@ public static bool TryReadInt32LittleEndian(ReadOnlySpan source, out int v } /// - /// Reads an Int64 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain an Int64, return false. + /// If the span is too small to contain a , return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadInt64LittleEndian(ReadOnlySpan source, out long value) { @@ -223,6 +269,40 @@ public static bool TryReadInt64LittleEndian(ReadOnlySpan source, out long return success; } + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// If the span is too small to contain a , return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadInt128LittleEndian(ReadOnlySpan source, out Int128 value) + { + if (BitConverter.IsLittleEndian) + { + return MemoryMarshal.TryRead(source, out value); + } + + bool success = MemoryMarshal.TryRead(source, out Int128 tmp); + value = ReverseEndianness(tmp); + return success; + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// If the span is too small to contain a , return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadIntPtrLittleEndian(ReadOnlySpan source, out nint value) + { + if (BitConverter.IsLittleEndian) + { + return MemoryMarshal.TryRead(source, out value); + } + + bool success = MemoryMarshal.TryRead(source, out nint tmp); + value = ReverseEndianness(tmp); + return success; + } + /// /// Reads a from the beginning of a read-only span of bytes, as little endian. /// @@ -245,9 +325,9 @@ public static bool TryReadSingleLittleEndian(ReadOnlySpan source, out floa } /// - /// Reads a UInt16 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain a UInt16, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt16LittleEndian(ReadOnlySpan source, out ushort value) @@ -263,9 +343,9 @@ public static bool TryReadUInt16LittleEndian(ReadOnlySpan source, out usho } /// - /// Reads a UInt32 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain a UInt32, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt32LittleEndian(ReadOnlySpan source, out uint value) @@ -281,9 +361,9 @@ public static bool TryReadUInt32LittleEndian(ReadOnlySpan source, out uint } /// - /// Reads a UInt64 out of a read-only span of bytes as little endian. + /// Reads a from the beginning of a read-only span of bytes, as little endian. /// - /// If the span is too small to contain a UInt64, return false. + /// If the span is too small to contain a , return false. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryReadUInt64LittleEndian(ReadOnlySpan source, out ulong value) @@ -297,5 +377,41 @@ public static bool TryReadUInt64LittleEndian(ReadOnlySpan source, out ulon value = ReverseEndianness(tmp); return success; } + + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// If the span is too small to contain a , return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadUInt128LittleEndian(ReadOnlySpan source, out UInt128 value) + { + if (BitConverter.IsLittleEndian) + { + return MemoryMarshal.TryRead(source, out value); + } + + bool success = MemoryMarshal.TryRead(source, out UInt128 tmp); + value = ReverseEndianness(tmp); + return success; + } + + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// If the span is too small to contain a , return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadUIntPtrLittleEndian(ReadOnlySpan source, out nuint value) + { + if (BitConverter.IsLittleEndian) + { + return MemoryMarshal.TryRead(source, out value); + } + + bool success = MemoryMarshal.TryRead(source, out nuint tmp); + value = ReverseEndianness(tmp); + return success; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs index 2c32bb0f685e3..a30ff594e04be 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs @@ -55,7 +55,7 @@ public static void WriteHalfBigEndian(Span destination, Half value) } /// - /// Writes an Int16 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt16BigEndian(Span destination, short value) @@ -72,7 +72,7 @@ public static void WriteInt16BigEndian(Span destination, short value) } /// - /// Writes an Int32 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt32BigEndian(Span destination, int value) @@ -89,7 +89,7 @@ public static void WriteInt32BigEndian(Span destination, int value) } /// - /// Writes an Int64 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt64BigEndian(Span destination, long value) @@ -105,6 +105,40 @@ public static void WriteInt64BigEndian(Span destination, long value) } } + /// + /// Writes a into a span of bytes, as big endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteInt128BigEndian(Span destination, Int128 value) + { + if (BitConverter.IsLittleEndian) + { + Int128 tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + /// + /// Writes a into a span of bytes, as big endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteIntPtrBigEndian(Span destination, nint value) + { + if (BitConverter.IsLittleEndian) + { + nint tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + /// /// Writes a into a span of bytes, as big endian. /// @@ -129,7 +163,7 @@ public static void WriteSingleBigEndian(Span destination, float value) } /// - /// Write a UInt16 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -147,7 +181,7 @@ public static void WriteUInt16BigEndian(Span destination, ushort value) } /// - /// Write a UInt32 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -165,7 +199,7 @@ public static void WriteUInt32BigEndian(Span destination, uint value) } /// - /// Write a UInt64 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -182,6 +216,42 @@ public static void WriteUInt64BigEndian(Span destination, ulong value) } } + /// + /// Writes a into a span of bytes, as big endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUInt128BigEndian(Span destination, UInt128 value) + { + if (BitConverter.IsLittleEndian) + { + UInt128 tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + /// + /// Writes a into a span of bytes, as big endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUIntPtrBigEndian(Span destination, nuint value) + { + if (BitConverter.IsLittleEndian) + { + nuint tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + /// /// Writes a into a span of bytes, as big endian. /// @@ -225,7 +295,7 @@ public static bool TryWriteHalfBigEndian(Span destination, Half value) } /// - /// Writes an Int16 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -241,7 +311,7 @@ public static bool TryWriteInt16BigEndian(Span destination, short value) } /// - /// Writes an Int32 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -257,7 +327,7 @@ public static bool TryWriteInt32BigEndian(Span destination, int value) } /// - /// Writes an Int64 into a span of bytes as big endian. + /// Writes a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -272,6 +342,38 @@ public static bool TryWriteInt64BigEndian(Span destination, long value) return MemoryMarshal.TryWrite(destination, ref value); } + /// + /// Writes a into a span of bytes, as big endian. + /// + /// If the span is too small to contain the value, return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteInt128BigEndian(Span destination, Int128 value) + { + if (BitConverter.IsLittleEndian) + { + Int128 tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + + /// + /// Writes a into a span of bytes, as big endian. + /// + /// If the span is too small to contain the value, return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteIntPtrBigEndian(Span destination, nint value) + { + if (BitConverter.IsLittleEndian) + { + nint tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + /// /// Writes a into a span of bytes, as big endian. /// @@ -294,7 +396,7 @@ public static bool TryWriteSingleBigEndian(Span destination, float value) } /// - /// Write a UInt16 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -311,7 +413,7 @@ public static bool TryWriteUInt16BigEndian(Span destination, ushort value) } /// - /// Write a UInt32 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -328,7 +430,7 @@ public static bool TryWriteUInt32BigEndian(Span destination, uint value) } /// - /// Write a UInt64 into a span of bytes as big endian. + /// Write a into a span of bytes, as big endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -343,5 +445,39 @@ public static bool TryWriteUInt64BigEndian(Span destination, ulong value) return MemoryMarshal.TryWrite(destination, ref value); } + + /// + /// Writes a into a span of bytes, as big endian. + /// + /// If the span is too small to contain the value, return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteUInt128BigEndian(Span destination, UInt128 value) + { + if (BitConverter.IsLittleEndian) + { + UInt128 tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + + /// + /// Writes a into a span of bytes, as big endian. + /// + /// If the span is too small to contain the value, return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteUIntPtrBigEndian(Span destination, nuint value) + { + if (BitConverter.IsLittleEndian) + { + nuint tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs index f88383490b513..efba216e68b43 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs @@ -55,7 +55,7 @@ public static void WriteHalfLittleEndian(Span destination, Half value) } /// - /// Writes an Int16 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt16LittleEndian(Span destination, short value) @@ -72,7 +72,7 @@ public static void WriteInt16LittleEndian(Span destination, short value) } /// - /// Writes an Int32 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt32LittleEndian(Span destination, int value) @@ -89,7 +89,7 @@ public static void WriteInt32LittleEndian(Span destination, int value) } /// - /// Writes an Int64 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteInt64LittleEndian(Span destination, long value) @@ -105,6 +105,40 @@ public static void WriteInt64LittleEndian(Span destination, long value) } } + /// + /// Writes a into a span of bytes, as little endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteInt128LittleEndian(Span destination, Int128 value) + { + if (!BitConverter.IsLittleEndian) + { + Int128 tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + /// + /// Writes a into a span of bytes, as little endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteIntPtrLittleEndian(Span destination, nint value) + { + if (!BitConverter.IsLittleEndian) + { + nint tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + /// /// Writes a into a span of bytes, as little endian. /// @@ -129,7 +163,7 @@ public static void WriteSingleLittleEndian(Span destination, float value) } /// - /// Write a UInt16 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -147,7 +181,7 @@ public static void WriteUInt16LittleEndian(Span destination, ushort value) } /// - /// Write a UInt32 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -165,7 +199,7 @@ public static void WriteUInt32LittleEndian(Span destination, uint value) } /// - /// Write a UInt64 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -182,6 +216,42 @@ public static void WriteUInt64LittleEndian(Span destination, ulong value) } } + /// + /// Writes a into a span of bytes, as little endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUInt128LittleEndian(Span destination, UInt128 value) + { + if (!BitConverter.IsLittleEndian) + { + UInt128 tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + + /// + /// Writes a into a span of bytes, as little endian. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUIntPtrLittleEndian(Span destination, nuint value) + { + if (!BitConverter.IsLittleEndian) + { + nuint tmp = ReverseEndianness(value); + MemoryMarshal.Write(destination, ref tmp); + } + else + { + MemoryMarshal.Write(destination, ref value); + } + } + /// /// Writes a into a span of bytes, as little endian. /// @@ -225,7 +295,7 @@ public static bool TryWriteHalfLittleEndian(Span destination, Half value) } /// - /// Writes an Int16 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -241,7 +311,7 @@ public static bool TryWriteInt16LittleEndian(Span destination, short value } /// - /// Writes an Int32 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -257,7 +327,7 @@ public static bool TryWriteInt32LittleEndian(Span destination, int value) } /// - /// Writes an Int64 into a span of bytes as little endian. + /// Writes a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -272,6 +342,38 @@ public static bool TryWriteInt64LittleEndian(Span destination, long value) return MemoryMarshal.TryWrite(destination, ref value); } + /// + /// Writes a into a span of bytes, as little endian. + /// + /// If the span is too small to contain the value, return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteInt128LittleEndian(Span destination, Int128 value) + { + if (!BitConverter.IsLittleEndian) + { + Int128 tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + + /// + /// Writes a into a span of bytes, as little endian. + /// + /// If the span is too small to contain the value, return false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteIntPtrLittleEndian(Span destination, nint value) + { + if (!BitConverter.IsLittleEndian) + { + nint tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + /// /// Writes a into a span of bytes, as little endian. /// @@ -294,7 +396,7 @@ public static bool TryWriteSingleLittleEndian(Span destination, float valu } /// - /// Write a UInt16 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -311,7 +413,7 @@ public static bool TryWriteUInt16LittleEndian(Span destination, ushort val } /// - /// Write a UInt32 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -328,7 +430,7 @@ public static bool TryWriteUInt32LittleEndian(Span destination, uint value } /// - /// Write a UInt64 into a span of bytes as little endian. + /// Write a into a span of bytes, as little endian. /// /// If the span is too small to contain the value, return false. [CLSCompliant(false)] @@ -343,5 +445,39 @@ public static bool TryWriteUInt64LittleEndian(Span destination, ulong valu return MemoryMarshal.TryWrite(destination, ref value); } + + /// + /// Writes a into a span of bytes, as little endian. + /// + /// If the span is too small to contain the value, return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteUInt128LittleEndian(Span destination, UInt128 value) + { + if (!BitConverter.IsLittleEndian) + { + UInt128 tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } + + /// + /// Writes a into a span of bytes, as little endian. + /// + /// If the span is too small to contain the value, return false. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteUIntPtrLittleEndian(Span destination, nuint value) + { + if (!BitConverter.IsLittleEndian) + { + nuint tmp = ReverseEndianness(value); + return MemoryMarshal.TryWrite(destination, ref tmp); + } + + return MemoryMarshal.TryWrite(destination, ref value); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs index a5c396cb207f0..ae97271568458 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs @@ -31,14 +31,7 @@ internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, R Type? enumType = parameterType.IsEnum ? Enum.GetUnderlyingType(parameterType) : null; if (parameterType == typeof(IntPtr)) { - if (IntPtr.Size == 8) - { - decodedFields[i] = (nint)BinaryPrimitives.ReadInt64LittleEndian(payload); - } - else - { - decodedFields[i] = (nint)BinaryPrimitives.ReadInt32LittleEndian(payload); - } + decodedFields[i] = BinaryPrimitives.ReadIntPtrLittleEndian(payload); payload = payload.Slice(IntPtr.Size); } else if (parameterType == typeof(int) || enumType == typeof(int)) @@ -83,12 +76,12 @@ internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, R } else if (parameterType == typeof(float)) { - decodedFields[i] = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(payload)); + decodedFields[i] = BinaryPrimitives.ReadSingleLittleEndian(payload); payload = payload.Slice(sizeof(float)); } else if (parameterType == typeof(double)) { - decodedFields[i] = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(payload)); + decodedFields[i] = BinaryPrimitives.ReadDoubleLittleEndian(payload); payload = payload.Slice(sizeof(double)); } else if (parameterType == typeof(bool)) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs index 0033453e93e0e..fe353d35e1c3a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs @@ -240,9 +240,9 @@ public virtual char ReadChar() public virtual long ReadInt64() => BinaryPrimitives.ReadInt64LittleEndian(InternalRead(8)); [CLSCompliant(false)] public virtual ulong ReadUInt64() => BinaryPrimitives.ReadUInt64LittleEndian(InternalRead(8)); - public virtual Half ReadHalf() => BitConverter.Int16BitsToHalf(BinaryPrimitives.ReadInt16LittleEndian(InternalRead(2))); - public virtual unsafe float ReadSingle() => BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(InternalRead(4))); - public virtual unsafe double ReadDouble() => BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(InternalRead(8))); + public virtual Half ReadHalf() => BinaryPrimitives.ReadHalfLittleEndian(InternalRead(2)); + public virtual float ReadSingle() => BinaryPrimitives.ReadSingleLittleEndian(InternalRead(4)); + public virtual double ReadDouble() => BinaryPrimitives.ReadDoubleLittleEndian(InternalRead(8)); public virtual decimal ReadDecimal() {