SpanReader<T>
Represents simple memory reader backed by ReadOnlySpan<T>.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[StructLayout(LayoutKind.Auto)]
[NullableContext(1)]
[Nullable(0)]
[CompilerFeatureRequired("RefStructs")]
public ref struct SpanReader<[Nullable(2)] T>
{
private readonly ref T reference;
private readonly int length;
private int position;
[IsReadOnly]
public unsafe ref T Current {
[IsReadOnly]
[return: IsReadOnly]
get {
if ((uint)position >= (uint)length)
<get_Current>g__ThrowInvalidOperationException|6_0();
return ref Unsafe.Add<T>(*(ref T*)(&reference), position);
}
}
public int ConsumedCount {
[IsReadOnly]
get {
return position;
}
set {
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)value, (uint)length, "value");
position = value;
}
}
public int RemainingCount {
[IsReadOnly]
get {
return length - position;
}
}
[Nullable(new byte[] {
0,
1
})]
public unsafe ReadOnlySpan<T> Span {
[IsReadOnly]
[return: Nullable(new byte[] {
0,
1
})]
get {
return MemoryMarshal.CreateReadOnlySpan<T>(*(ref T*)(&reference), length);
}
}
[Nullable(new byte[] {
0,
1
})]
public unsafe ReadOnlySpan<T> ConsumedSpan {
[IsReadOnly]
[return: Nullable(new byte[] {
0,
1
})]
get {
return MemoryMarshal.CreateReadOnlySpan<T>(*(ref T*)(&reference), position);
}
}
[Nullable(new byte[] {
0,
1
})]
public unsafe ReadOnlySpan<T> RemainingSpan {
[IsReadOnly]
[return: Nullable(new byte[] {
0,
1
})]
get {
return MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(*(ref T*)(&reference), position), RemainingCount);
}
}
public unsafe SpanReader([Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> span)
{
position = 0;
*(ref T*)(&reference) = ref MemoryMarshal.GetReference<T>(span);
length = span.Length;
}
public unsafe SpanReader(ref T reference, int length)
{
position = 0;
if (length < 0)
throw new ArgumentOutOfRangeException("length");
if (length > 0 && Unsafe.IsNullRef<T>(ref reference))
throw new ArgumentNullException("reference");
*(ref T*)(&this.reference) = ref reference;
this.length = length;
}
public void Advance(int count)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)count, (uint)RemainingCount, "count");
position += count;
}
public void Rewind(int count)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)count, (uint)position, "count");
position -= count;
}
public void Reset()
{
position = 0;
}
public bool TryRead([ScopedRef] [Nullable(new byte[] {
0,
1
})] Span<T> output)
{
if (TryRead(output.Length, out ReadOnlySpan<T> result))
return result.TryCopyTo(output);
return false;
}
public unsafe bool TryRead(int count, [Nullable(new byte[] {
0,
1
})] out ReadOnlySpan<T> result)
{
ArgumentOutOfRangeException.ThrowIfNegative<int>(count, "count");
int num = position + count;
if ((uint)num <= (uint)length) {
result = MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(*(ref T*)(&reference), position), count);
position = num;
return true;
}
result = default(ReadOnlySpan<T>);
return false;
}
public unsafe bool TryRead([MaybeNullWhen(false)] out T result)
{
if ((uint)position < (uint)length) {
result = Unsafe.Add<T>(*(ref T*)(&reference), position++);
return true;
}
result = default(T);
return false;
}
public int Read([ScopedRef] [Nullable(new byte[] {
0,
1
})] Span<T> output)
{
DotNext.Span.CopyTo<T>(RemainingSpan, output, out int writtenCount);
position += writtenCount;
return writtenCount;
}
[return: IsReadOnly]
public unsafe ref T Read()
{
if ((uint)position >= (uint)length)
ThrowInternalBufferOverflowException();
return ref Unsafe.Add<T>(*(ref T*)(&reference), position++);
}
[return: Nullable(new byte[] {
0,
1
})]
public ReadOnlySpan<T> Read(int count)
{
if (!TryRead(count, out ReadOnlySpan<T> result))
ThrowInternalBufferOverflowException();
return result;
}
[DoesNotReturn]
[StackTraceHidden]
private static void ThrowInternalBufferOverflowException()
{
throw new InternalBufferOverflowException();
}
[CLSCompliant(false)]
public unsafe TResult Read<[Nullable(2)] TResult>([Nullable(new byte[] {
0,
1,
0,
1
})] IntPtr reader, int count)
{
ArgumentNullException.ThrowIfNull((void*)(long)reader, "reader");
if (!this.TryRead(count, out ReadOnlySpan<T> result))
SpanReader<T>.ThrowInternalBufferOverflowException();
return (TResult);
}
[CLSCompliant(false)]
public unsafe bool TryRead<[Nullable(2)] TResult>([Nullable(new byte[] {
0,
1,
0,
1
})] IntPtr reader, int count, [MaybeNullWhen(false)] out TResult result)
{
ArgumentNullException.ThrowIfNull((void*)(long)reader, "reader");
if (this.TryRead(count, out ReadOnlySpan<T> result2)) {
result = (TResult);
return true;
}
result = default(TResult);
return false;
}
[return: Nullable(new byte[] {
0,
1
})]
public ReadOnlySpan<T> ReadToEnd()
{
ReadOnlySpan<T> remainingSpan = RemainingSpan;
position = length;
return remainingSpan;
}
[IsReadOnly]
public override string ToString()
{
return ConsumedSpan.ToString();
}
}
}