[API Proposal]: SequenceReader missing endian-aware read methods for C# built-in ValueTypes
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- csharp
- Domain
- backend-api-design
Research direction
Start by reviewing the existing endian-aware methods on SequenceReaderExtensions and the related BinaryPrimitives support mentioned in the proposal. Check how SequenceReader handles split sequences and how the proposed built-in types, especially decimal, map to existing APIs. Done means reaching an agreed API design and adding the corresponding implementation and tests.
Written by the indexing model from the issue text.
Description
Background and motivation:
As the SequenceReader is a component quite commonly used in the performance optimized System.IO.Pipelines API, it would be nice for it to have a full complement of low level Read methods which are endian-aware (such that higher level code appears clean and consistent in accessing the lower level memory sequences presented by the System.IO.Pipelines APIs and others).
There is support for some of the C# built-in types, but many are currently lacking.
API Proposal:
The addition of the following methods:
namespace System.Buffers;
public static partial class SequenceReaderExtensions
{
...
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out ushort value;
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out uint value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out ulong value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out ulong value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out nint value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out nuint value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.Int128 value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.UInt128 value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.Half value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out single value);
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out double value);
...
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out ushort value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out uint value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out ulong value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out nint value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out nuint value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.Int128 value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.UInt128 value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out System.Half value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out single value);
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out double value);
...
}
I also believe that consideration should be given to supporting the decimal C# datatype as well.
namespace System.Buffers;
public static partial class SequenceReaderExtensions
{
+ //NOTE: Throws NotImplemented on LittleEndian architecture
+ public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out decimal value);
+ //NOTE: Throws NotImplemented on BigEndian architecture
+ public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out decimal value);
}
The reason I believe this should be considered is not strictly for the Endian handling aspect, but more for the Sequence handling aspect.
As the decimal is a native C# type, when using the SequenceReader API it doesn't feel appropriate that an API-user would need to concern themselves over re-assembling this native C# type themselves from potentially split sequences.
With the decimal being constructed of a 96bit integer, and a 32 bit flag, I'm unsure how it would strictly be handled in terms of endian swapping. I would however suggest that the API should be included in the SequenceReader, for completeness, but where the opposing read (BigEndian on little endian architecture and vice versa) would throw a NotImplemented exception. The current implementation could then only handle the endianness of the architecture until BinaryPrimatives supports this handling also.
API Usage:
using System.Buffers;
namespace My.Magic.Bus;
public struct MyCustomStruct
{
public uint CustomerIndex;
public decimal CustomersBigMoney;
}
public static class MyCustomStructSequenceReaderExtensions
{
public static bool TryReadBigEndian(this ref System.Buffers.SequenceReader<byte> reader, out MyCustomStruct value)
{
MyCustomStruct temp;
bool success = true;
success &= reader.TryReadBigEndian(out temp.CustomerIndex);
success &= reader.TryReadBigEndian(out temp.CustomersBigMoney);
value = temp;
return success;
}
public static bool TryReadLittleEndian(this ref System.Buffers.SequenceReader<byte> reader, out MyCustomStruct value)
{
MyCustomStruct temp;
bool success = true;
success &= reader.TryReadLittleEndian(out temp.CustomerIndex);
success &= reader.TryReadLittleEndian(out temp.CustomersBigMoney);
value = temp;
return success;
}
}
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 589
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dotnet/runtime
-
agentic-workflows untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
area-System.Reflection blocking-clean-ci-optional Known Build Error os-mac-os-x untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
area-CodeGen-coreclr untriaged
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
agentic-workflows untriaged
Difficulty 1/5 Under an hour Newbie friendliness 78/100
-
area-VM-meta-mono untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Similar issues
-
bug documentation frontend
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
azurenoops/spin_agent#975 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
:watch: Not Triaged 11.0 fundamentals/subsvc
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
dotnet/AspNetCore.Docs#37699 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15108 · 1 comment ·
-
area/docs-content Bug pulumi/docs
Difficulty 1/5 1-3 hours Newbie friendliness 94/100