Skip to content

Commit

Permalink
Add notes for System.Binary
Browse files Browse the repository at this point in the history
  • Loading branch information
terrajobst committed Oct 3, 2017
1 parent 3915cb5 commit 6ef6b5d
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 0 deletions.
86 changes: 86 additions & 0 deletions 2017/10-03-System.Binary/README.md
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`.
94 changes: 94 additions & 0 deletions 2017/10-03-System.Binary/System.Binary.md
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);
}
}
```

0 comments on commit 6ef6b5d

Please sign in to comment.