-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3915cb5
commit 6ef6b5d
Showing
2 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# System.Binary | ||
|
||
Status: **Needs more work** | ||
| [Issue](https://github.com/dotnet/corefx/issues/24144 ) | ||
| [API Ref](System.Binary.md) | ||
| [Video](https://www.youtube.com/watch?v=m4BUM3nJZRw&t=404s) | ||
|
||
## Notes | ||
|
||
* Extension methods | ||
- If we want to expose them as extension methods we need to have both | ||
overloads for `ReadOnlySpan<T>` and `Span<T>` | ||
- Let's do non-extension methods for now; we can make them extension methods | ||
later. | ||
+ But let's leave the type name to be `BinaryPrimitives` (as opposed to | ||
`BufferExtensions`) | ||
+ But we should still put them in a separate namespace so that making | ||
them extension methods later, developers can decide whether they get | ||
these extensions by importing/not importing the namespace | ||
* Endianness | ||
- Is there any point in having both little & big endian? Default seems to be | ||
little endian | ||
+ Yes, we need to support parsing from the networking, which is | ||
generally big endian. We could remove `LittleEndian` by making it the | ||
default, given that all machines are basically little endian, but that | ||
seems weird if we ever have to support a big endian machine. Seems | ||
it's better to be consistent and explicit. | ||
- Can we collapse the endianness methods into overloads with making it | ||
argument? | ||
+ No, because we'd probably lose some performance | ||
* `Reverse` | ||
- The proposed (generic) API we have for reversing bytes doesn't work | ||
because endianness has to be done at the granularity of smaller types | ||
(int, long) etc. Hence, we removed it. | ||
- `Reverse(byte)` seems weird. Was only added to allow code to be converted | ||
with forcing folks to add/remove `Reverse()` calls. | ||
- Should we rename `Reverse` to `ReverseEndianness`? | ||
* `Read<T>`/`Write<T>` | ||
- Can we remove the specialized reader/writer methods in favor of the | ||
generic `Read<T>`/`Write<T>` method? | ||
+ No, because the generic method cannot handle endianness. | ||
- `Read<T>`/`Write<T>` should be renamed so that the name indicates it uses | ||
machine endianness | ||
- Should `Read<T>` return a `ref T`? | ||
+ No, because that wouldn't guarantee any alignment. Returning a `T` | ||
guarantees that it's aligned because we always align the stack | ||
- Should `Write<T>` take a `ref T`? | ||
+ Probably yes | ||
- Should we rename `ReadXxx` and `WriteXxx` to `GetXxx`/`SetXxx`? The name | ||
seems to imply an updated cursor. | ||
+ No, because that name would feel weird when called as a static. | ||
+ Let's leave them as `ReadXxx` and `WriteXxx` | ||
|
||
## Namespace | ||
|
||
The family of `Span<T>` features is across these namespaces: | ||
|
||
* `System` | ||
- `Span<T>` | ||
- `Memory<T>` | ||
* `System.Buffers` | ||
- `OwnedMemory<T>` | ||
- Lifetime managers | ||
* `System.Buffers.Text` | ||
- Formatting & parsing | ||
* `System.Buffers.Binary` | ||
- The type discussed here | ||
- `BinaryExtensions` | ||
|
||
Thus, using `System.Buffers.Binary` feels very consistent. | ||
|
||
## Assemblies | ||
|
||
The family of `Span<T>` exists across these assemblies: | ||
|
||
1. `System.Memory` | ||
- OOB `Span<T>` | ||
- Later type forwarded to the core library where span is in-box | ||
2. `System.Buffers` | ||
- Already contains the existing V1 `ArrayPool` | ||
|
||
(1) has to be in-box | ||
(2) doesn't have to be, but might due to `ArrayPool`. In fact, on .NET Core | ||
`ArrayPool` lives in `System.Private.Corelib` | ||
|
||
For now, we've decided to put `BinaryExtensions` into `System.Buffers`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# System.Binary | ||
|
||
```C# | ||
namespace System.Buffers { | ||
public static class Binary { | ||
public static T Read<T>(this ReadOnlySpan<byte> buffer) where T : struct; | ||
public static T Read<T>(this Span<byte> buffer) where T : struct; | ||
public static short ReadInt16BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static short ReadInt16BigEndian(this Span<byte> buffer); | ||
public static short ReadInt16LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static short ReadInt16LittleEndian(this Span<byte> buffer); | ||
public static int ReadInt32BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static int ReadInt32BigEndian(this Span<byte> buffer); | ||
public static int ReadInt32LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static int ReadInt32LittleEndian(this Span<byte> buffer); | ||
public static long ReadInt64BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static long ReadInt64BigEndian(this Span<byte> buffer); | ||
public static long ReadInt64LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static long ReadInt64LittleEndian(this Span<byte> buffer); | ||
public static ushort ReadUInt16BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static ushort ReadUInt16BigEndian(this Span<byte> buffer); | ||
public static ushort ReadUInt16LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static ushort ReadUInt16LittleEndian(this Span<byte> buffer); | ||
public static uint ReadUInt32BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static uint ReadUInt32BigEndian(this Span<byte> buffer); | ||
public static uint ReadUInt32LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static uint ReadUInt32LittleEndian(this Span<byte> buffer); | ||
public static ulong ReadUInt64BigEndian(this ReadOnlySpan<byte> buffer); | ||
public static ulong ReadUInt64BigEndian(this Span<byte> buffer); | ||
public static ulong ReadUInt64LittleEndian(this ReadOnlySpan<byte> buffer); | ||
public static ulong ReadUInt64LittleEndian(this Span<byte> buffer); | ||
public static byte Reverse(this byte value); | ||
public static short Reverse(this short value); | ||
public static int Reverse(this int value); | ||
public static long Reverse(this long value); | ||
public static sbyte Reverse(this sbyte value); | ||
public static ushort Reverse(this ushort value); | ||
public static uint Reverse(this uint value); | ||
public static ulong Reverse(this ulong value); | ||
public static bool TryRead<T>(this ReadOnlySpan<byte> buffer, out T value) where T : struct; | ||
public static bool TryRead<T>(this Span<byte> buffer, out T value) where T : struct; | ||
public static bool TryReadInt16BigEndian(this ReadOnlySpan<byte> buffer, out short value); | ||
public static bool TryReadInt16BigEndian(this Span<byte> buffer, out short value); | ||
public static bool TryReadInt16LittleEndian(this ReadOnlySpan<byte> buffer, out short value); | ||
public static bool TryReadInt16LittleEndian(this Span<byte> buffer, out short value); | ||
public static bool TryReadInt32BigEndian(this ReadOnlySpan<byte> buffer, out int value); | ||
public static bool TryReadInt32BigEndian(this Span<byte> buffer, out int value); | ||
public static bool TryReadInt32LittleEndian(this ReadOnlySpan<byte> buffer, out int value); | ||
public static bool TryReadInt32LittleEndian(this Span<byte> buffer, out int value); | ||
public static bool TryReadInt64BigEndian(this ReadOnlySpan<byte> buffer, out long value); | ||
public static bool TryReadInt64BigEndian(this Span<byte> buffer, out long value); | ||
public static bool TryReadInt64LittleEndian(this ReadOnlySpan<byte> buffer, out long value); | ||
public static bool TryReadInt64LittleEndian(this Span<byte> buffer, out long value); | ||
public static bool TryReadUInt16BigEndian(this ReadOnlySpan<byte> buffer, out ushort value); | ||
public static bool TryReadUInt16BigEndian(this Span<byte> buffer, out ushort value); | ||
public static bool TryReadUInt16LittleEndian(this ReadOnlySpan<byte> buffer, out ushort value); | ||
public static bool TryReadUInt16LittleEndian(this Span<byte> buffer, out ushort value); | ||
public static bool TryReadUInt32BigEndian(this ReadOnlySpan<byte> buffer, out uint value); | ||
public static bool TryReadUInt32BigEndian(this Span<byte> buffer, out uint value); | ||
public static bool TryReadUInt32LittleEndian(this ReadOnlySpan<byte> buffer, out uint value); | ||
public static bool TryReadUInt32LittleEndian(this Span<byte> buffer, out uint value); | ||
public static bool TryReadUInt64BigEndian(this ReadOnlySpan<byte> buffer, out ulong value); | ||
public static bool TryReadUInt64BigEndian(this Span<byte> buffer, out ulong value); | ||
public static bool TryReadUInt64LittleEndian(this ReadOnlySpan<byte> buffer, out ulong value); | ||
public static bool TryReadUInt64LittleEndian(this Span<byte> buffer, out ulong value); | ||
public static bool TryWrite<T>(this Span<byte> buffer, T value) where T : struct; | ||
public static bool TryWriteInt16BigEndian(this Span<byte> buffer, short value); | ||
public static bool TryWriteInt16LittleEndian(this Span<byte> buffer, short value); | ||
public static bool TryWriteInt32BigEndian(this Span<byte> buffer, int value); | ||
public static bool TryWriteInt32LittleEndian(this Span<byte> buffer, int value); | ||
public static bool TryWriteInt64BigEndian(this Span<byte> buffer, long value); | ||
public static bool TryWriteInt64LittleEndian(this Span<byte> buffer, long value); | ||
public static bool TryWriteUInt16BigEndian(this Span<byte> buffer, ushort value); | ||
public static bool TryWriteUInt16LittleEndian(this Span<byte> buffer, ushort value); | ||
public static bool TryWriteUInt32BigEndian(this Span<byte> buffer, uint value); | ||
public static bool TryWriteUInt32LittleEndian(this Span<byte> buffer, uint value); | ||
public static bool TryWriteUInt64BigEndian(this Span<byte> buffer, ulong value); | ||
public static bool TryWriteUInt64LittleEndian(this Span<byte> buffer, ulong value); | ||
public static void Write<T>(this Span<byte> buffer, T value) where T : struct; | ||
public static void WriteInt16BigEndian(this Span<byte> buffer, short value); | ||
public static void WriteInt16LittleEndian(this Span<byte> buffer, short value); | ||
public static void WriteInt32BigEndian(this Span<byte> buffer, int value); | ||
public static void WriteInt32LittleEndian(this Span<byte> buffer, int value); | ||
public static void WriteInt64BigEndian(this Span<byte> buffer, long value); | ||
public static void WriteInt64LittleEndian(this Span<byte> buffer, long value); | ||
public static void WriteUInt16BigEndian(this Span<byte> buffer, ushort value); | ||
public static void WriteUInt16LittleEndian(this Span<byte> buffer, ushort value); | ||
public static void WriteUInt32BigEndian(this Span<byte> buffer, uint value); | ||
public static void WriteUInt32LittleEndian(this Span<byte> buffer, uint value); | ||
public static void WriteUInt64BigEndian(this Span<byte> buffer, ulong value); | ||
public static void WriteUInt64LittleEndian(this Span<byte> buffer, ulong value); | ||
} | ||
} | ||
``` |