Add Single and Double overloads to BinaryPrimitives (#6864)
authorEric Erhardt <eric.erhardt@microsoft.com>
Mon, 3 Feb 2020 23:48:01 +0000 (17:48 -0600)
committerGitHub <noreply@github.com>
Mon, 3 Feb 2020 23:48:01 +0000 (17:48 -0600)
* Add Single and Double overloads to BinaryPrimitives

Fix #2365

src/libraries/System.Memory/ref/System.Memory.cs
src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs
src/libraries/System.Memory/tests/Binary/BinaryWriterUnitTests.cs
src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/Reader.cs
src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/ReaderBigEndian.cs
src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/ReaderLittleEndian.cs
src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/WriterBigEndian.cs
src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/WriterLittleEndian.cs

index bc17f4d..db2eeba 100644 (file)
@@ -315,12 +315,16 @@ namespace System.Buffers.Binary
 {
     public static partial class BinaryPrimitives
     {
+        public static double ReadDoubleBigEndian(System.ReadOnlySpan<byte> source) { throw null; }
+        public static double ReadDoubleLittleEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static short ReadInt16BigEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static short ReadInt16LittleEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static int ReadInt32BigEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static int ReadInt32LittleEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static long ReadInt64BigEndian(System.ReadOnlySpan<byte> source) { throw null; }
         public static long ReadInt64LittleEndian(System.ReadOnlySpan<byte> source) { throw null; }
+        public static float ReadSingleBigEndian(System.ReadOnlySpan<byte> source) { throw null; }
+        public static float ReadSingleLittleEndian(System.ReadOnlySpan<byte> source) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static ushort ReadUInt16BigEndian(System.ReadOnlySpan<byte> source) { throw null; }
         [System.CLSCompliantAttribute(false)]
@@ -345,12 +349,16 @@ namespace System.Buffers.Binary
         public static uint ReverseEndianness(uint value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static ulong ReverseEndianness(ulong value) { throw null; }
+        public static bool TryReadDoubleBigEndian(System.ReadOnlySpan<byte> source, out double value) { throw null; }
+        public static bool TryReadDoubleLittleEndian(System.ReadOnlySpan<byte> source, out double value) { throw null; }
         public static bool TryReadInt16BigEndian(System.ReadOnlySpan<byte> source, out short value) { throw null; }
         public static bool TryReadInt16LittleEndian(System.ReadOnlySpan<byte> source, out short value) { throw null; }
         public static bool TryReadInt32BigEndian(System.ReadOnlySpan<byte> source, out int value) { throw null; }
         public static bool TryReadInt32LittleEndian(System.ReadOnlySpan<byte> source, out int value) { throw null; }
         public static bool TryReadInt64BigEndian(System.ReadOnlySpan<byte> source, out long value) { throw null; }
         public static bool TryReadInt64LittleEndian(System.ReadOnlySpan<byte> source, out long value) { throw null; }
+        public static bool TryReadSingleBigEndian(System.ReadOnlySpan<byte> source, out float value) { throw null; }
+        public static bool TryReadSingleLittleEndian(System.ReadOnlySpan<byte> source, out float value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static bool TryReadUInt16BigEndian(System.ReadOnlySpan<byte> source, out ushort value) { throw null; }
         [System.CLSCompliantAttribute(false)]
@@ -363,12 +371,16 @@ namespace System.Buffers.Binary
         public static bool TryReadUInt64BigEndian(System.ReadOnlySpan<byte> source, out ulong value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static bool TryReadUInt64LittleEndian(System.ReadOnlySpan<byte> source, out ulong value) { throw null; }
+        public static bool TryWriteDoubleBigEndian(System.Span<byte> destination, double value) { throw null; }
+        public static bool TryWriteDoubleLittleEndian(System.Span<byte> destination, double value) { throw null; }
         public static bool TryWriteInt16BigEndian(System.Span<byte> destination, short value) { throw null; }
         public static bool TryWriteInt16LittleEndian(System.Span<byte> destination, short value) { throw null; }
         public static bool TryWriteInt32BigEndian(System.Span<byte> destination, int value) { throw null; }
         public static bool TryWriteInt32LittleEndian(System.Span<byte> destination, int value) { throw null; }
         public static bool TryWriteInt64BigEndian(System.Span<byte> destination, long value) { throw null; }
         public static bool TryWriteInt64LittleEndian(System.Span<byte> destination, long value) { throw null; }
+        public static bool TryWriteSingleBigEndian(System.Span<byte> destination, float value) { throw null; }
+        public static bool TryWriteSingleLittleEndian(System.Span<byte> destination, float value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static bool TryWriteUInt16BigEndian(System.Span<byte> destination, ushort value) { throw null; }
         [System.CLSCompliantAttribute(false)]
@@ -381,12 +393,16 @@ namespace System.Buffers.Binary
         public static bool TryWriteUInt64BigEndian(System.Span<byte> destination, ulong value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static bool TryWriteUInt64LittleEndian(System.Span<byte> destination, ulong value) { throw null; }
+        public static void WriteDoubleBigEndian(System.Span<byte> destination, double value) { }
+        public static void WriteDoubleLittleEndian(System.Span<byte> destination, double value) { }
         public static void WriteInt16BigEndian(System.Span<byte> destination, short value) { }
         public static void WriteInt16LittleEndian(System.Span<byte> destination, short value) { }
         public static void WriteInt32BigEndian(System.Span<byte> destination, int value) { }
         public static void WriteInt32LittleEndian(System.Span<byte> destination, int value) { }
         public static void WriteInt64BigEndian(System.Span<byte> destination, long value) { }
         public static void WriteInt64LittleEndian(System.Span<byte> destination, long value) { }
+        public static void WriteSingleBigEndian(System.Span<byte> destination, float value) { }
+        public static void WriteSingleLittleEndian(System.Span<byte> destination, float value) { }
         [System.CLSCompliantAttribute(false)]
         public static void WriteUInt16BigEndian(System.Span<byte> destination, ushort value) { }
         [System.CLSCompliantAttribute(false)]
index 355a5d3..6448cd3 100644 (file)
@@ -79,6 +79,26 @@ namespace System.Buffers.Binary.Tests
             Assert.Equal<long>(unchecked((long)0x8877665544332211), ReadInt64LittleEndian(span));
             Assert.True(TryReadInt64LittleEndian(span, out longValue));
             Assert.Equal<long>(unchecked((long)0x8877665544332211), longValue);
+
+            float expectedFloat = BitConverter.Int32BitsToSingle(0x11223344);
+            Assert.Equal<float>(expectedFloat, ReadSingleBigEndian(span));
+            Assert.True(TryReadSingleBigEndian(span, out float floatValue));
+            Assert.Equal<float>(expectedFloat, floatValue);
+
+            expectedFloat = BitConverter.Int32BitsToSingle(0x44332211);
+            Assert.Equal<float>(expectedFloat, ReadSingleLittleEndian(span));
+            Assert.True(TryReadSingleLittleEndian(span, out floatValue));
+            Assert.Equal<float>(expectedFloat, floatValue);
+
+            double expectedDouble = BitConverter.Int64BitsToDouble(0x1122334455667788);
+            Assert.Equal<double>(expectedDouble, ReadDoubleBigEndian(span));
+            Assert.True(TryReadDoubleBigEndian(span, out double doubleValue));
+            Assert.Equal<double>(expectedDouble, doubleValue);
+
+            expectedDouble = BitConverter.Int64BitsToDouble(unchecked((long)0x8877665544332211));
+            Assert.Equal<double>(expectedDouble, ReadDoubleLittleEndian(span));
+            Assert.True(TryReadDoubleLittleEndian(span, out doubleValue));
+            Assert.Equal<double>(expectedDouble, doubleValue);
         }
 
         [Fact]
@@ -148,6 +168,26 @@ namespace System.Buffers.Binary.Tests
             Assert.Equal<long>(unchecked((long)0x8877665544332211), ReadInt64LittleEndian(span));
             Assert.True(TryReadInt64LittleEndian(span, out longValue));
             Assert.Equal<long>(unchecked((long)0x8877665544332211), longValue);
+
+            float expectedFloat = BitConverter.Int32BitsToSingle(0x11223344);
+            Assert.Equal<float>(expectedFloat, ReadSingleBigEndian(span));
+            Assert.True(TryReadSingleBigEndian(span, out float floatValue));
+            Assert.Equal<float>(expectedFloat, floatValue);
+
+            expectedFloat = BitConverter.Int32BitsToSingle(0x44332211);
+            Assert.Equal<float>(expectedFloat, ReadSingleLittleEndian(span));
+            Assert.True(TryReadSingleLittleEndian(span, out floatValue));
+            Assert.Equal<float>(expectedFloat, floatValue);
+
+            double expectedDouble = BitConverter.Int64BitsToDouble(0x1122334455667788);
+            Assert.Equal<double>(expectedDouble, ReadDoubleBigEndian(span));
+            Assert.True(TryReadDoubleBigEndian(span, out double doubleValue));
+            Assert.Equal<double>(expectedDouble, doubleValue);
+
+            expectedDouble = BitConverter.Int64BitsToDouble(unchecked((long)0x8877665544332211));
+            Assert.Equal<double>(expectedDouble, ReadDoubleLittleEndian(span));
+            Assert.True(TryReadDoubleLittleEndian(span, out doubleValue));
+            Assert.Equal<double>(expectedDouble, doubleValue);
         }
 
         [Fact]
@@ -173,6 +213,11 @@ namespace System.Buffers.Binary.Tests
             TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<ulong>(_span));
             Assert.False(MemoryMarshal.TryRead(span, out ulong ulongValue));
 
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<float>(_span));
+            Assert.False(MemoryMarshal.TryRead(span, out float floatValue));
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<double>(_span));
+            Assert.False(MemoryMarshal.TryRead(span, out double doubleValue));
+
             Span<byte> largeSpan = new byte[100];
             TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => MemoryMarshal.Read<TestHelpers.TestValueTypeWithReference>(_span));
             TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => MemoryMarshal.TryRead(_span, out TestHelpers.TestValueTypeWithReference stringValue));
@@ -201,6 +246,11 @@ namespace System.Buffers.Binary.Tests
             TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<ulong>(_span));
             Assert.False(MemoryMarshal.TryRead(span, out ulong ulongValue));
 
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<float>(_span));
+            Assert.False(MemoryMarshal.TryRead(span, out float floatValue));
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Read<double>(_span));
+            Assert.False(MemoryMarshal.TryRead(span, out double doubleValue));
+
             ReadOnlySpan<byte> largeSpan = new byte[100];
             TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => MemoryMarshal.Read<TestHelpers.TestValueTypeWithReference>(_span));
             TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => MemoryMarshal.TryRead(_span, out TestHelpers.TestValueTypeWithReference stringValue));
@@ -219,12 +269,16 @@ namespace System.Buffers.Binary.Tests
             WriteUInt16BigEndian(spanBE.Slice(14), s_testStruct.US0);
             WriteUInt32BigEndian(spanBE.Slice(16), s_testStruct.UI0);
             WriteUInt64BigEndian(spanBE.Slice(20), s_testStruct.UL0);
-            WriteInt16BigEndian(spanBE.Slice(28), s_testStruct.S1);
-            WriteInt32BigEndian(spanBE.Slice(30), s_testStruct.I1);
-            WriteInt64BigEndian(spanBE.Slice(34), s_testStruct.L1);
-            WriteUInt16BigEndian(spanBE.Slice(42), s_testStruct.US1);
-            WriteUInt32BigEndian(spanBE.Slice(44), s_testStruct.UI1);
-            WriteUInt64BigEndian(spanBE.Slice(48), s_testStruct.UL1);
+            WriteSingleBigEndian(spanBE.Slice(28), s_testStruct.F0);
+            WriteDoubleBigEndian(spanBE.Slice(32), s_testStruct.D0);
+            WriteInt16BigEndian(spanBE.Slice(40), s_testStruct.S1);
+            WriteInt32BigEndian(spanBE.Slice(42), s_testStruct.I1);
+            WriteInt64BigEndian(spanBE.Slice(46), s_testStruct.L1);
+            WriteUInt16BigEndian(spanBE.Slice(54), s_testStruct.US1);
+            WriteUInt32BigEndian(spanBE.Slice(56), s_testStruct.UI1);
+            WriteUInt64BigEndian(spanBE.Slice(60), s_testStruct.UL1);
+            WriteSingleBigEndian(spanBE.Slice(68), s_testStruct.F1);
+            WriteDoubleBigEndian(spanBE.Slice(72), s_testStruct.D1);
 
             ReadOnlySpan<byte> readOnlySpanBE = new ReadOnlySpan<byte>(spanBE.ToArray());
 
@@ -236,12 +290,16 @@ namespace System.Buffers.Binary.Tests
                 US0 = ReadUInt16BigEndian(spanBE.Slice(14)),
                 UI0 = ReadUInt32BigEndian(spanBE.Slice(16)),
                 UL0 = ReadUInt64BigEndian(spanBE.Slice(20)),
-                S1 = ReadInt16BigEndian(spanBE.Slice(28)),
-                I1 = ReadInt32BigEndian(spanBE.Slice(30)),
-                L1 = ReadInt64BigEndian(spanBE.Slice(34)),
-                US1 = ReadUInt16BigEndian(spanBE.Slice(42)),
-                UI1 = ReadUInt32BigEndian(spanBE.Slice(44)),
-                UL1 = ReadUInt64BigEndian(spanBE.Slice(48))
+                F0 = ReadSingleBigEndian(spanBE.Slice(28)),
+                D0 = ReadDoubleBigEndian(spanBE.Slice(32)),
+                S1 = ReadInt16BigEndian(spanBE.Slice(40)),
+                I1 = ReadInt32BigEndian(spanBE.Slice(42)),
+                L1 = ReadInt64BigEndian(spanBE.Slice(46)),
+                US1 = ReadUInt16BigEndian(spanBE.Slice(54)),
+                UI1 = ReadUInt32BigEndian(spanBE.Slice(56)),
+                UL1 = ReadUInt64BigEndian(spanBE.Slice(60)),
+                F1 = ReadSingleBigEndian(spanBE.Slice(68)),
+                D1 = ReadDoubleBigEndian(spanBE.Slice(72))
             };
 
             var readStructFromReadOnlySpan = new TestStruct
@@ -252,12 +310,16 @@ namespace System.Buffers.Binary.Tests
                 US0 = ReadUInt16BigEndian(readOnlySpanBE.Slice(14)),
                 UI0 = ReadUInt32BigEndian(readOnlySpanBE.Slice(16)),
                 UL0 = ReadUInt64BigEndian(readOnlySpanBE.Slice(20)),
-                S1 = ReadInt16BigEndian(readOnlySpanBE.Slice(28)),
-                I1 = ReadInt32BigEndian(readOnlySpanBE.Slice(30)),
-                L1 = ReadInt64BigEndian(readOnlySpanBE.Slice(34)),
-                US1 = ReadUInt16BigEndian(readOnlySpanBE.Slice(42)),
-                UI1 = ReadUInt32BigEndian(readOnlySpanBE.Slice(44)),
-                UL1 = ReadUInt64BigEndian(readOnlySpanBE.Slice(48))
+                F0 = ReadSingleBigEndian(readOnlySpanBE.Slice(28)),
+                D0 = ReadDoubleBigEndian(readOnlySpanBE.Slice(32)),
+                S1 = ReadInt16BigEndian(readOnlySpanBE.Slice(40)),
+                I1 = ReadInt32BigEndian(readOnlySpanBE.Slice(42)),
+                L1 = ReadInt64BigEndian(readOnlySpanBE.Slice(46)),
+                US1 = ReadUInt16BigEndian(readOnlySpanBE.Slice(54)),
+                UI1 = ReadUInt32BigEndian(readOnlySpanBE.Slice(56)),
+                UL1 = ReadUInt64BigEndian(readOnlySpanBE.Slice(60)),
+                F1 = ReadSingleBigEndian(readOnlySpanBE.Slice(68)),
+                D1 = ReadDoubleBigEndian(readOnlySpanBE.Slice(72))
             };
 
             Assert.Equal(s_testStruct, readStruct);
@@ -277,12 +339,16 @@ namespace System.Buffers.Binary.Tests
             WriteUInt16LittleEndian(spanLE.Slice(14), s_testStruct.US0);
             WriteUInt32LittleEndian(spanLE.Slice(16), s_testStruct.UI0);
             WriteUInt64LittleEndian(spanLE.Slice(20), s_testStruct.UL0);
-            WriteInt16LittleEndian(spanLE.Slice(28), s_testStruct.S1);
-            WriteInt32LittleEndian(spanLE.Slice(30), s_testStruct.I1);
-            WriteInt64LittleEndian(spanLE.Slice(34), s_testStruct.L1);
-            WriteUInt16LittleEndian(spanLE.Slice(42), s_testStruct.US1);
-            WriteUInt32LittleEndian(spanLE.Slice(44), s_testStruct.UI1);
-            WriteUInt64LittleEndian(spanLE.Slice(48), s_testStruct.UL1);
+            WriteSingleLittleEndian(spanLE.Slice(28), s_testStruct.F0);
+            WriteDoubleLittleEndian(spanLE.Slice(32), s_testStruct.D0);
+            WriteInt16LittleEndian(spanLE.Slice(40), s_testStruct.S1);
+            WriteInt32LittleEndian(spanLE.Slice(42), s_testStruct.I1);
+            WriteInt64LittleEndian(spanLE.Slice(46), s_testStruct.L1);
+            WriteUInt16LittleEndian(spanLE.Slice(54), s_testStruct.US1);
+            WriteUInt32LittleEndian(spanLE.Slice(56), s_testStruct.UI1);
+            WriteUInt64LittleEndian(spanLE.Slice(60), s_testStruct.UL1);
+            WriteSingleLittleEndian(spanLE.Slice(68), s_testStruct.F1);
+            WriteDoubleLittleEndian(spanLE.Slice(72), s_testStruct.D1);
 
             ReadOnlySpan<byte> readOnlySpanLE = new ReadOnlySpan<byte>(spanLE.ToArray());
 
@@ -294,12 +360,16 @@ namespace System.Buffers.Binary.Tests
                 US0 = ReadUInt16LittleEndian(spanLE.Slice(14)),
                 UI0 = ReadUInt32LittleEndian(spanLE.Slice(16)),
                 UL0 = ReadUInt64LittleEndian(spanLE.Slice(20)),
-                S1 = ReadInt16LittleEndian(spanLE.Slice(28)),
-                I1 = ReadInt32LittleEndian(spanLE.Slice(30)),
-                L1 = ReadInt64LittleEndian(spanLE.Slice(34)),
-                US1 = ReadUInt16LittleEndian(spanLE.Slice(42)),
-                UI1 = ReadUInt32LittleEndian(spanLE.Slice(44)),
-                UL1 = ReadUInt64LittleEndian(spanLE.Slice(48))
+                F0 = ReadSingleLittleEndian(spanLE.Slice(28)),
+                D0 = ReadDoubleLittleEndian(spanLE.Slice(32)),
+                S1 = ReadInt16LittleEndian(spanLE.Slice(40)),
+                I1 = ReadInt32LittleEndian(spanLE.Slice(42)),
+                L1 = ReadInt64LittleEndian(spanLE.Slice(46)),
+                US1 = ReadUInt16LittleEndian(spanLE.Slice(54)),
+                UI1 = ReadUInt32LittleEndian(spanLE.Slice(56)),
+                UL1 = ReadUInt64LittleEndian(spanLE.Slice(60)),
+                F1 = ReadSingleLittleEndian(spanLE.Slice(68)),
+                D1 = ReadDoubleLittleEndian(spanLE.Slice(72))
             };
 
             var readStructFromReadOnlySpan = new TestStruct
@@ -310,12 +380,16 @@ namespace System.Buffers.Binary.Tests
                 US0 = ReadUInt16LittleEndian(readOnlySpanLE.Slice(14)),
                 UI0 = ReadUInt32LittleEndian(readOnlySpanLE.Slice(16)),
                 UL0 = ReadUInt64LittleEndian(readOnlySpanLE.Slice(20)),
-                S1 = ReadInt16LittleEndian(readOnlySpanLE.Slice(28)),
-                I1 = ReadInt32LittleEndian(readOnlySpanLE.Slice(30)),
-                L1 = ReadInt64LittleEndian(readOnlySpanLE.Slice(34)),
-                US1 = ReadUInt16LittleEndian(readOnlySpanLE.Slice(42)),
-                UI1 = ReadUInt32LittleEndian(readOnlySpanLE.Slice(44)),
-                UL1 = ReadUInt64LittleEndian(readOnlySpanLE.Slice(48))
+                F0 = ReadSingleLittleEndian(readOnlySpanLE.Slice(28)),
+                D0 = ReadDoubleLittleEndian(readOnlySpanLE.Slice(32)),
+                S1 = ReadInt16LittleEndian(readOnlySpanLE.Slice(40)),
+                I1 = ReadInt32LittleEndian(readOnlySpanLE.Slice(42)),
+                L1 = ReadInt64LittleEndian(readOnlySpanLE.Slice(46)),
+                US1 = ReadUInt16LittleEndian(readOnlySpanLE.Slice(54)),
+                UI1 = ReadUInt32LittleEndian(readOnlySpanLE.Slice(56)),
+                UL1 = ReadUInt64LittleEndian(readOnlySpanLE.Slice(60)),
+                F1 = ReadSingleLittleEndian(readOnlySpanLE.Slice(68)),
+                D1 = ReadDoubleLittleEndian(readOnlySpanLE.Slice(72))
             };
 
             Assert.Equal(s_testStruct, readStruct);
@@ -442,12 +516,16 @@ namespace System.Buffers.Binary.Tests
             US0 = ushort.MaxValue,
             UI0 = uint.MaxValue,
             UL0 = ulong.MaxValue,
+            F0 = float.MaxValue,
+            D0 = double.MaxValue,
             S1 = short.MinValue,
             I1 = int.MinValue,
             L1 = long.MinValue,
             US1 = ushort.MinValue,
             UI1 = uint.MinValue,
-            UL1 = ulong.MinValue
+            UL1 = ulong.MinValue,
+            F1 = float.MinValue,
+            D1 = double.MinValue,
         };
 
         [StructLayout(LayoutKind.Sequential)]
@@ -459,12 +537,16 @@ namespace System.Buffers.Binary.Tests
             public ushort US0;
             public uint UI0;
             public ulong UL0;
+            public float F0;
+            public double D0;
             public short S1;
             public int I1;
             public long L1;
             public ushort US1;
             public uint UI1;
             public ulong UL1;
+            public float F1;
+            public double D1;
         }
     }
 }
index 766fc52..78724c5 100644 (file)
@@ -65,6 +65,18 @@ namespace System.Buffers.Binary.Tests
             TestHelpers.Validate<long>(span, longValue);
             Assert.True(MemoryMarshal.TryWrite<long>(span, ref longValue));
             TestHelpers.Validate<long>(span, longValue);
+
+            float floatValue = BitConverter.Int32BitsToSingle(0x11223344);
+            MemoryMarshal.Write<float>(span, ref floatValue);
+            TestHelpers.Validate<float>(span, floatValue);
+            Assert.True(MemoryMarshal.TryWrite<float>(span, ref floatValue));
+            TestHelpers.Validate<float>(span, floatValue);
+
+            double doubleValue = BitConverter.Int64BitsToDouble(0x1122334455667788);
+            MemoryMarshal.Write<double>(span, ref doubleValue);
+            TestHelpers.Validate<double>(span, doubleValue);
+            Assert.True(MemoryMarshal.TryWrite<double>(span, ref doubleValue));
+            TestHelpers.Validate<double>(span, doubleValue);
         }
 
         [Theory]
@@ -257,6 +269,68 @@ namespace System.Buffers.Binary.Tests
             Assert.Equal(value, read);
         }
 
+        [Theory]
+        [InlineData(float.MaxValue)]
+        [InlineData(float.MinValue)]
+        [InlineData(float.Epsilon)]
+        [InlineData(float.PositiveInfinity)]
+        [InlineData(float.NegativeInfinity)]
+        [InlineData(float.NaN)]
+        public void SpanWriteSingle(float value)
+        {
+            Assert.True(BitConverter.IsLittleEndian);
+            var span = new Span<byte>(new byte[4]);
+            WriteSingleBigEndian(span, value);
+            float read = ReadSingleBigEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            Assert.True(TryWriteSingleBigEndian(span, value));
+            read = ReadSingleBigEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            WriteSingleLittleEndian(span, value);
+            read = ReadSingleLittleEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            Assert.True(TryWriteSingleLittleEndian(span, value));
+            read = ReadSingleLittleEndian(span);
+            Assert.Equal(value, read);
+        }
+
+        [Theory]
+        [InlineData(double.MaxValue)]
+        [InlineData(double.MinValue)]
+        [InlineData(double.Epsilon)]
+        [InlineData(double.PositiveInfinity)]
+        [InlineData(double.NegativeInfinity)]
+        [InlineData(double.NaN)]
+        public void SpanWriteDouble(double value)
+        {
+            Assert.True(BitConverter.IsLittleEndian);
+            var span = new Span<byte>(new byte[8]);
+            WriteDoubleBigEndian(span, value);
+            double read = ReadDoubleBigEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            Assert.True(TryWriteDoubleBigEndian(span, value));
+            read = ReadDoubleBigEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            WriteDoubleLittleEndian(span, value);
+            read = ReadDoubleLittleEndian(span);
+            Assert.Equal(value, read);
+
+            span.Clear();
+            Assert.True(TryWriteDoubleLittleEndian(span, value));
+            read = ReadDoubleLittleEndian(span);
+            Assert.Equal(value, read);
+        }
+
         [Fact]
         public void SpanWriteFail()
         {
@@ -268,6 +342,8 @@ namespace System.Buffers.Binary.Tests
             uint uintValue = 1;
             long longValue = 1;
             ulong ulongValue = 1;
+            float floatValue = 1;
+            double doubleValue = 1;
 
             Span<byte> span = new byte[1];
 
@@ -303,6 +379,11 @@ namespace System.Buffers.Binary.Tests
             TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write<ulong>(_span, ref ulongValue));
             Assert.False(MemoryMarshal.TryWrite<ulong>(span, ref ulongValue));
 
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write<float>(_span, ref floatValue));
+            Assert.False(MemoryMarshal.TryWrite<float>(span, ref floatValue));
+            TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write<double>(_span, ref doubleValue));
+            Assert.False(MemoryMarshal.TryWrite<double>(span, ref doubleValue));
+
             var structValue = new TestHelpers.TestValueTypeWithReference { I = 1, S = "1" };
             TestHelpers.AssertThrows<ArgumentException, byte>(span, (_span) => MemoryMarshal.Write<TestHelpers.TestValueTypeWithReference>(_span, ref structValue));
             TestHelpers.AssertThrows<ArgumentException, byte>(span, (_span) => MemoryMarshal.TryWrite<TestHelpers.TestValueTypeWithReference>(_span, ref structValue));
index 069636b..e564ab8 100644 (file)
@@ -23,10 +23,7 @@ namespace System.Buffers.Binary
         /// </summary>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static sbyte ReverseEndianness(sbyte value)
-        {
-            return value;
-        }
+        public static sbyte ReverseEndianness(sbyte value) => value;
 
         /// <summary>
         /// Reverses a primitive value - performs an endianness swap
@@ -55,10 +52,7 @@ namespace System.Buffers.Binary
         /// rather than having to skip byte fields.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static byte ReverseEndianness(byte value)
-        {
-            return value;
-        }
+        public static byte ReverseEndianness(byte value) => value;
 
         /// <summary>
         /// Reverses a primitive value - performs an endianness swap
index 03b4e76..c1a2736 100644 (file)
@@ -10,6 +10,23 @@ namespace System.Buffers.Binary
     public static partial class BinaryPrimitives
     {
         /// <summary>
+        /// Reads a <see cref="double" /> from the beginning of a read-only span of bytes, as big endian.
+        /// </summary>
+        /// <param name="source">The read-only span to read.</param>
+        /// <returns>The big endian value.</returns>
+        /// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="source"/> is too small to contain a <see cref="double" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static double ReadDoubleBigEndian(ReadOnlySpan<byte> source)
+        {
+            return BitConverter.IsLittleEndian ?
+                BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read<long>(source))) :
+                MemoryMarshal.Read<double>(source);
+        }
+
+        /// <summary>
         /// Reads an Int16 out of a read-only span of bytes as big endian.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -52,6 +69,23 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="float" /> from the beginning of a read-only span of bytes, as big endian.
+        /// </summary>
+        /// <param name="source">The read-only span to read.</param>
+        /// <returns>The big endian value.</returns>
+        /// <remarks>Reads exactly 4 bytes from the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="source"/> is too small to contain a <see cref="float" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float ReadSingleBigEndian(ReadOnlySpan<byte> source)
+        {
+            return BitConverter.IsLittleEndian ?
+                BitConverter.Int32BitsToSingle(ReverseEndianness(MemoryMarshal.Read<int>(source))) :
+                MemoryMarshal.Read<float>(source);
+        }
+
+        /// <summary>
         /// Reads a UInt16 out of a read-only span of bytes as big endian.
         /// </summary>
         [CLSCompliant(false)]
@@ -97,9 +131,31 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="double" /> from the beginning of a read-only span of bytes, as big endian.
+        /// </summary>
+        /// <param name="source">The read-only span of bytes to read.</param>
+        /// <param name="value">When this method returns, the value read out of the read-only span of bytes, as big endian.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> source, out double value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                bool success = MemoryMarshal.TryRead(source, out long tmp);
+                value = BitConverter.Int64BitsToDouble(ReverseEndianness(tmp));
+                return success;
+            }
+
+            return MemoryMarshal.TryRead(source, out value);
+        }
+
+        /// <summary>
         /// Reads an Int16 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain an Int16, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int16, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt16BigEndian(ReadOnlySpan<byte> source, out short value)
         {
@@ -115,8 +171,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads an Int32 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain an Int32, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int32, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt32BigEndian(ReadOnlySpan<byte> source, out int value)
         {
@@ -132,8 +188,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads an Int64 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain an Int64, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int64, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt64BigEndian(ReadOnlySpan<byte> source, out long value)
         {
@@ -148,9 +204,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="float" /> from the beginning of a read-only span of bytes, as big endian.
+        /// </summary>
+        /// <param name="source">The read-only span of bytes to read.</param>
+        /// <param name="value">When this method returns, the value read out of the read-only span of bytes, as big endian.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="float" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Reads exactly 4 bytes from the beginning of the span.</remarks>
+        public static bool TryReadSingleBigEndian(ReadOnlySpan<byte> source, out float value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                bool success = MemoryMarshal.TryRead(source, out int tmp);
+                value = BitConverter.Int32BitsToSingle(ReverseEndianness(tmp));
+                return success;
+            }
+
+            return MemoryMarshal.TryRead(source, out value);
+        }
+
+        /// <summary>
         /// Reads a UInt16 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain a UInt16, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt16, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt16BigEndian(ReadOnlySpan<byte> source, out ushort value)
@@ -167,8 +244,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads a UInt32 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain a UInt32, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt32, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt32BigEndian(ReadOnlySpan<byte> source, out uint value)
@@ -185,8 +262,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads a UInt64 out of a read-only span of bytes as big endian.
-        /// <returns>If the span is too small to contain a UInt64, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt64, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt64BigEndian(ReadOnlySpan<byte> source, out ulong value)
index d4520c0..a93c29c 100644 (file)
@@ -10,6 +10,23 @@ namespace System.Buffers.Binary
     public static partial class BinaryPrimitives
     {
         /// <summary>
+        /// Reads a <see cref="double" /> from the beginning of a read-only span of bytes, as little endian.
+        /// </summary>
+        /// <param name="source">The read-only span to read.</param>
+        /// <returns>The little endian value.</returns>
+        /// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="source"/> is too small to contain a <see cref="double" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static double ReadDoubleLittleEndian(ReadOnlySpan<byte> source)
+        {
+            return !BitConverter.IsLittleEndian ?
+                BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read<long>(source))) :
+                MemoryMarshal.Read<double>(source);
+        }
+
+        /// <summary>
         /// Reads an Int16 out of a read-only span of bytes as little endian.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -52,6 +69,23 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="float" /> from the beginning of a read-only span of bytes, as little endian.
+        /// </summary>
+        /// <param name="source">The read-only span to read.</param>
+        /// <returns>The little endian value.</returns>
+        /// <remarks>Reads exactly 4 bytes from the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="source"/> is too small to contain a <see cref="float" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float ReadSingleLittleEndian(ReadOnlySpan<byte> source)
+        {
+            return !BitConverter.IsLittleEndian ?
+                BitConverter.Int32BitsToSingle(ReverseEndianness(MemoryMarshal.Read<int>(source))) :
+                MemoryMarshal.Read<float>(source);
+        }
+
+        /// <summary>
         /// Reads a UInt16 out of a read-only span of bytes as little endian.
         /// </summary>
         [CLSCompliant(false)]
@@ -97,9 +131,31 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="double" /> from the beginning of a read-only span of bytes, as little endian.
+        /// </summary>
+        /// <param name="source">The read-only span of bytes to read.</param>
+        /// <param name="value">When this method returns, the value read out of the read-only span of bytes, as little endian.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> source, out double value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                bool success = MemoryMarshal.TryRead(source, out long tmp);
+                value = BitConverter.Int64BitsToDouble(ReverseEndianness(tmp));
+                return success;
+            }
+
+            return MemoryMarshal.TryRead(source, out value);
+        }
+
+        /// <summary>
         /// Reads an Int16 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain an Int16, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int16, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt16LittleEndian(ReadOnlySpan<byte> source, out short value)
         {
@@ -115,8 +171,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads an Int32 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain an Int32, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int32, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt32LittleEndian(ReadOnlySpan<byte> source, out int value)
         {
@@ -132,8 +188,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads an Int64 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain an Int64, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain an Int64, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadInt64LittleEndian(ReadOnlySpan<byte> source, out long value)
         {
@@ -148,9 +204,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Reads a <see cref="float" /> from the beginning of a read-only span of bytes, as little endian.
+        /// </summary>
+        /// <param name="source">The read-only span of bytes to read.</param>
+        /// <param name="value">When this method returns, the value read out of the read-only span of bytes, as little endian.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="float" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Reads exactly 4 bytes from the beginning of the span.</remarks>
+        public static bool TryReadSingleLittleEndian(ReadOnlySpan<byte> source, out float value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                bool success = MemoryMarshal.TryRead(source, out int tmp);
+                value = BitConverter.Int32BitsToSingle(ReverseEndianness(tmp));
+                return success;
+            }
+
+            return MemoryMarshal.TryRead(source, out value);
+        }
+
+        /// <summary>
         /// Reads a UInt16 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain a UInt16, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt16, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt16LittleEndian(ReadOnlySpan<byte> source, out ushort value)
@@ -167,8 +244,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads a UInt32 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain a UInt32, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt32, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt32LittleEndian(ReadOnlySpan<byte> source, out uint value)
@@ -185,8 +262,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Reads a UInt64 out of a read-only span of bytes as little endian.
-        /// <returns>If the span is too small to contain a UInt64, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain a UInt64, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryReadUInt64LittleEndian(ReadOnlySpan<byte> source, out ulong value)
index 78be9b5..6d00181 100644 (file)
@@ -10,6 +10,29 @@ namespace System.Buffers.Binary
     public static partial class BinaryPrimitives
     {
         /// <summary>
+        /// Writes a <see cref="double" /> into a span of bytes, as big endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as big endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="destination" /> is too small to contain a <see cref="double" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteDoubleBigEndian(Span<byte> destination, double value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
+                MemoryMarshal.Write(destination, ref tmp);
+            }
+            else
+            {
+                MemoryMarshal.Write(destination, ref value);
+            }
+        }
+
+        /// <summary>
         /// Writes an Int16 into a span of bytes as big endian.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -49,6 +72,29 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="float" /> into a span of bytes, as big endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as big endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <remarks>Writes exactly 4 bytes to the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="destination" /> is too small to contain a <see cref="float" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteSingleBigEndian(Span<byte> destination, float value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                int tmp = ReverseEndianness(BitConverter.SingleToInt32Bits(value));
+                MemoryMarshal.Write(destination, ref tmp);
+            }
+            else
+            {
+                MemoryMarshal.Write(destination, ref value);
+            }
+        }
+
+        /// <summary>
         /// Write a UInt16 into a span of bytes as big endian.
         /// </summary>
         [CLSCompliant(false)]
@@ -91,9 +137,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="double" /> into a span of bytes, as big endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as big endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryWriteDoubleBigEndian(Span<byte> destination, double value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
+                return MemoryMarshal.TryWrite(destination, ref tmp);
+            }
+
+            return MemoryMarshal.TryWrite(destination, ref value);
+        }
+
+        /// <summary>
         /// Writes an Int16 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt16BigEndian(Span<byte> destination, short value)
         {
@@ -106,8 +173,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Writes an Int32 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt32BigEndian(Span<byte> destination, int value)
         {
@@ -120,8 +187,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Writes an Int64 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt64BigEndian(Span<byte> destination, long value)
         {
@@ -133,9 +200,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="float" /> into a span of bytes, as big endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as big endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="float" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Writes exactly 4 bytes to the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryWriteSingleBigEndian(Span<byte> destination, float value)
+        {
+            if (BitConverter.IsLittleEndian)
+            {
+                int tmp = ReverseEndianness(BitConverter.SingleToInt32Bits(value));
+                return MemoryMarshal.TryWrite(destination, ref tmp);
+            }
+
+            return MemoryMarshal.TryWrite(destination, ref value);
+        }
+
+        /// <summary>
         /// Write a UInt16 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt16BigEndian(Span<byte> destination, ushort value)
@@ -149,8 +237,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Write a UInt32 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt32BigEndian(Span<byte> destination, uint value)
@@ -164,8 +252,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Write a UInt64 into a span of bytes as big endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt64BigEndian(Span<byte> destination, ulong value)
index 5d63ee5..0fccd5a 100644 (file)
@@ -10,6 +10,29 @@ namespace System.Buffers.Binary
     public static partial class BinaryPrimitives
     {
         /// <summary>
+        /// Writes a <see cref="double" /> into a span of bytes, as little endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="destination" /> is too small to contain a <see cref="double" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteDoubleLittleEndian(Span<byte> destination, double value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
+                MemoryMarshal.Write(destination, ref tmp);
+            }
+            else
+            {
+                MemoryMarshal.Write(destination, ref value);
+            }
+        }
+
+        /// <summary>
         /// Writes an Int16 into a span of bytes as little endian.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -49,6 +72,29 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="float" /> into a span of bytes, as little endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <remarks>Writes exactly 4 bytes to the beginning of the span.</remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="destination" /> is too small to contain a <see cref="float" />.
+        /// </exception>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteSingleLittleEndian(Span<byte> destination, float value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                int tmp = ReverseEndianness(BitConverter.SingleToInt32Bits(value));
+                MemoryMarshal.Write(destination, ref tmp);
+            }
+            else
+            {
+                MemoryMarshal.Write(destination, ref value);
+            }
+        }
+
+        /// <summary>
         /// Write a UInt16 into a span of bytes as little endian.
         /// </summary>
         [CLSCompliant(false)]
@@ -91,9 +137,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="double" /> into a span of bytes, as little endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryWriteDoubleLittleEndian(Span<byte> destination, double value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
+                return MemoryMarshal.TryWrite(destination, ref tmp);
+            }
+
+            return MemoryMarshal.TryWrite(destination, ref value);
+        }
+
+        /// <summary>
         /// Writes an Int16 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt16LittleEndian(Span<byte> destination, short value)
         {
@@ -106,8 +173,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Writes an Int32 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt32LittleEndian(Span<byte> destination, int value)
         {
@@ -120,8 +187,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Writes an Int64 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteInt64LittleEndian(Span<byte> destination, long value)
         {
@@ -133,9 +200,30 @@ namespace System.Buffers.Binary
         }
 
         /// <summary>
+        /// Writes a <see cref="float" /> into a span of bytes, as little endian.
+        /// </summary>
+        /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param>
+        /// <param name="value">The value to write into the span of bytes.</param>
+        /// <returns>
+        /// <see langword="true" /> if the span is large enough to contain a <see cref="float" />; otherwise, <see langword="false" />.
+        /// </returns>
+        /// <remarks>Writes exactly 4 bytes to the beginning of the span.</remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryWriteSingleLittleEndian(Span<byte> destination, float value)
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                int tmp = ReverseEndianness(BitConverter.SingleToInt32Bits(value));
+                return MemoryMarshal.TryWrite(destination, ref tmp);
+            }
+
+            return MemoryMarshal.TryWrite(destination, ref value);
+        }
+
+        /// <summary>
         /// Write a UInt16 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt16LittleEndian(Span<byte> destination, ushort value)
@@ -149,8 +237,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Write a UInt32 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt32LittleEndian(Span<byte> destination, uint value)
@@ -164,8 +252,8 @@ namespace System.Buffers.Binary
 
         /// <summary>
         /// Write a UInt64 into a span of bytes as little endian.
-        /// <returns>If the span is too small to contain the value, return false.</returns>
         /// </summary>
+        /// <returns>If the span is too small to contain the value, return false.</returns>
         [CLSCompliant(false)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool TryWriteUInt64LittleEndian(Span<byte> destination, ulong value)