We currently have overloads to read short, int, long, etc for big and little endian. However, we don't have overloads for float and double. We should add them to complete the types that are supported by this class.
```C#
namespace System.Buffers.Binary
{
public static class BinaryPrimitives
{
public static float ReadSingleBigEndian(ReadOnlySpan
public static float ReadSingleLittleEndian(ReadOnlySpan
public static double ReadDoubleBigEndian(ReadOnlySpan
public static double ReadDoubleLittleEndian(ReadOnlySpan
public static bool TryReadSingleBigEndian(ReadOnlySpan<byte> buffer, out float value);
public static bool TryReadSingleLittleEndian(ReadOnlySpan<byte> buffer, out float value);
public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> buffer, out double value);
public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> buffer, out double value);
public static bool TryWriteSingleBigEndian(System.Span<byte> destination, float value);
public static bool TryWriteSingleLittleEndian(System.Span<byte> destination, float value);
public static bool TryWriteDoubleBigEndian(System.Span<byte> destination, double value);
public static bool TryWriteDoubleLittleEndian(System.Span<byte> destination, double value);
public static void WriteSingleBigEndian(System.Span<byte> destination, float value);
public static void WriteSingleLittleEndian(System.Span<byte> destination, float value);
public static void WriteDoubleBigEndian(System.Span<byte> destination, double value);
public static void WriteDoubleLittleEndian(System.Span<byte> destination, double value);
}
}
This API is useful when you are reading/writing to a memory stream that you know is little or big endian. For example, it would have been useful in the following code in the C# implementation of Google FlatBuffers:
Write float/double LittleEndian
https://github.com/google/flatbuffers/blob/1c7d91cc55a9deb05e7ea93ba10b5ab511d29238/net/FlatBuffers/ByteBuffer.cs#L509-L547
Read float/double LittleEndian
https://github.com/google/flatbuffers/blob/1c7d91cc55a9deb05e7ea93ba10b5ab511d29238/net/FlatBuffers/ByteBuffer.cs#L710-L750
A possible workaround is to make 2 calls like the following:
```C#
return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(buffer));
@stephentoub @jkotas @ahsonkhan @GrabYourPitchforks @tannergooding
We should also consider System.Decimal here. CC. @pentp
What does it mean to write decimal in big-endian / little-endian / machine-endian format?
Decimal uses 4 ints internally so its in-memory layout depends on endianess. All the existing (de)serialization methods on decimal/BinaryReader/BinaryWriter use the little-endian memory representation.
While initially it felt like this would be the best place for decimal<->Span APIs also, it looks like the original proposal in dotnet/corefx#35877 might actually be better for API discoverability and there is probably no need for big-endian decimal encodings.
Marking this as ready for review in order to move this proposal forward.
ReverseEndianness(float)ReverseEndianness(double)```C#
namespace System.Buffers.Binary
{
public static class BinaryPrimitives
{
public static float ReadSingleBigEndian(ReadOnlySpan
public static float ReadSingleLittleEndian(ReadOnlySpan
public static double ReadDoubleBigEndian(ReadOnlySpan
public static double ReadDoubleLittleEndian(ReadOnlySpan
public static bool TryReadSingleBigEndian(ReadOnlySpan<byte> buffer, out float value);
public static bool TryReadSingleLittleEndian(ReadOnlySpan<byte> buffer, out float value);
public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> buffer, out double value);
public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> buffer, out double value);
public static bool TryWriteSingleBigEndian(System.Span<byte> destination, float value);
public static bool TryWriteSingleLittleEndian(System.Span<byte> destination, float value);
public static bool TryWriteDoubleBigEndian(System.Span<byte> destination, double value);
public static bool TryWriteDoubleLittleEndian(System.Span<byte> destination, double value);
public static void WriteSingleBigEndian(System.Span<byte> destination, float value);
public static void WriteSingleLittleEndian(System.Span<byte> destination, float value);
public static void WriteDoubleBigEndian(System.Span<byte> destination, double value);
public static void WriteDoubleLittleEndian(System.Span<byte> destination, double value);
}
}
```
ReverseEndianness(float)
ReverseEndianness(double)
These do not make sense. They would produce completely bogus combination of bits that do not look anything like a valid floating point number (different from the integer overloads).
I believe the purpose of said APIs is to workaround limitations in other APIs. That is, not every API exposes the underlying Span<T>/ReadOnlySpan<T> and not every API exposes Read/Write methods that take endianness into account.
ReverseEndianness then lets you efficiently fixup the endianness to be a valid set of floating-point bits.
You can always use the longer form: BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(buffer))
Storing random bit pattern into a floating point register:
For consistency with existing APIs on BinaryPrimitives, the span parameter for the {Try}Read* APIs should be called source and not buffer. Just an FYI for whoever picks this issue up. The {Try}Write* APIs are correct:
-public static float ReadSingleBigEndian(ReadOnlySpan<byte> buffer);
-public static float ReadSingleLittleEndian(ReadOnlySpan<byte> buffer);
-public static double ReadDoubleBigEndian(ReadOnlySpan<byte> buffer);
-public static double ReadDoubleLittleEndian(ReadOnlySpan<byte> buffer);
+public static float ReadSingleBigEndian(ReadOnlySpan<byte> source);
+public static float ReadSingleLittleEndian(ReadOnlySpan<byte> source);
+public static double ReadDoubleBigEndian(ReadOnlySpan<byte> source);
+public static double ReadDoubleLittleEndian(ReadOnlySpan<byte> source);
-public static bool TryReadSingleBigEndian(ReadOnlySpan<byte> buffer, out float value);
-public static bool TryReadSingleLittleEndian(ReadOnlySpan<byte> buffer, out float value);
-public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> buffer, out double value);
-public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> buffer, out double value);
+public static bool TryReadSingleBigEndian(ReadOnlySpan<byte> source, out float value);
+public static bool TryReadSingleLittleEndian(ReadOnlySpan<byte> source, out float value);
+public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> source, out double value);
+public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> source, out double value);
re-adding api approved label
Most helpful comment
We should also consider
System.Decimalhere. CC. @pentp