From e94a024265d4c1df503ce2d6ad85066a1a0deaee Mon Sep 17 00:00:00 2001 From: ektrah Date: Sat, 4 May 2024 13:50:35 +0200 Subject: [PATCH] Use Range to simplify Asn1Reader --- src/Experimental/Asn1/Asn1Reader.cs | 95 ++++++++--------------------- 1 file changed, 26 insertions(+), 69 deletions(-) diff --git a/src/Experimental/Asn1/Asn1Reader.cs b/src/Experimental/Asn1/Asn1Reader.cs index 4699d3d8..797047dd 100644 --- a/src/Experimental/Asn1/Asn1Reader.cs +++ b/src/Experimental/Asn1/Asn1Reader.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Runtime.CompilerServices; using NSec.Cryptography; @@ -10,7 +9,7 @@ internal ref struct Asn1Reader { internal const int MaxDepth = 7; - private InlineSpanArray _stack; + private InlineRangeArray _stack; private readonly ReadOnlySpan _buffer; private int _depth; private bool _failed; @@ -18,8 +17,8 @@ internal ref struct Asn1Reader public Asn1Reader( ReadOnlySpan buffer) { - _stack = new InlineSpanArray(); - _stack[0] = new Span(buffer); + _stack = new InlineRangeArray(); + _stack[0] = Range.All; _buffer = buffer; _depth = 0; @@ -28,11 +27,11 @@ public Asn1Reader( public readonly bool Success => !_failed; - public readonly bool SuccessComplete => !_failed && _depth == 0 && _stack[0].IsEmpty; + public readonly bool SuccessComplete => !_failed && _depth == 0 && _buffer[_stack[0]].IsEmpty; public void BeginSequence() { - Span span = Read(0x30); + Range range = Read(0x30); if (_failed) { @@ -45,13 +44,13 @@ public void BeginSequence() { throw Error.InvalidOperation_InternalError(); // overflow } - _stack[_depth] = span; + _stack[_depth] = range; } } public ReadOnlySpan BitString() { - ReadOnlySpan bytes = Read(0x03).ApplyTo(_buffer); + ReadOnlySpan bytes = _buffer[Read(0x03)]; ReadOnlySpan value = default; if (_failed || bytes.IsEmpty || bytes[0] != 0) @@ -68,7 +67,7 @@ public ReadOnlySpan BitString() public bool Bool() { - ReadOnlySpan bytes = Read(0x01).ApplyTo(_buffer); + ReadOnlySpan bytes = _buffer[Read(0x01)]; bool value = default; if (_failed || bytes.Length != 1 || (bytes[0] != 0x00 && bytes[0] != 0xFF)) @@ -85,7 +84,7 @@ public bool Bool() public void End() { - if (_failed || !_stack[_depth].IsEmpty) + if (_failed || !_buffer[_stack[_depth]].IsEmpty) { Fail(); } @@ -101,7 +100,7 @@ public void End() public int Integer32() { - ReadOnlySpan bytes = Read(0x02).ApplyTo(_buffer); + ReadOnlySpan bytes = _buffer[Read(0x02)]; int value = default; if (_failed || IsInvalidInteger(bytes, sizeof(int))) @@ -122,7 +121,7 @@ public int Integer32() public long Integer64() { - ReadOnlySpan bytes = Read(0x02).ApplyTo(_buffer); + ReadOnlySpan bytes = _buffer[Read(0x02)]; long value = default; if (_failed || IsInvalidInteger(bytes, sizeof(long))) @@ -143,9 +142,9 @@ public long Integer64() public void Null() { - Span span = Read(0x05); + ReadOnlySpan bytes = _buffer[Read(0x05)]; - if (_failed || !span.IsEmpty) + if (_failed || !bytes.IsEmpty) { Fail(); } @@ -153,12 +152,12 @@ public void Null() public ReadOnlySpan ObjectIdentifier() { - return Read(0x06).ApplyTo(_buffer); + return _buffer[Read(0x06)]; } public ReadOnlySpan OctetString() { - return Read(0x04).ApplyTo(_buffer); + return _buffer[Read(0x04)]; } private void Fail() @@ -178,18 +177,18 @@ private readonly bool IsInvalidInteger( || bytes.Length > 1 && bytes[0] == 0xFF && (bytes[1] & 0x80) == 0x80; } - private Span Read( + private Range Read( int tag) { - Span span = _stack[_depth]; - ReadOnlySpan bytes = span.ApplyTo(_buffer); + Range range = _stack[_depth]; + ReadOnlySpan bytes = _buffer[range]; if (_failed || bytes.Length < 2 || bytes[0] != tag) { goto failed; } - int start = 2; + int offset = 2; int length = 0; if ((bytes[1] & ~0x7F) == 0) @@ -205,7 +204,7 @@ private Span Read( } while (count-- > 0) { - length = (length << 8) | bytes[start++]; + length = (length << 8) | bytes[offset++]; } if (length < 0x80) { @@ -213,65 +212,23 @@ private Span Read( } } - if (length > bytes.Length - start) + if (length > bytes.Length - offset) { goto failed; } - _stack[_depth] = span[(start + length)..]; - return span.Slice(start, length); + (int Offset, int Length) = range.GetOffsetAndLength(_buffer.Length); + _stack[_depth] = new Range(Offset + offset + length, Offset + Length); + return new Range(Offset + offset, Offset + offset + length); failed: Fail(); return default; } [InlineArray(MaxDepth)] - private struct InlineSpanArray + private struct InlineRangeArray { - private Span _element0; - } - - private readonly struct Span - { - private readonly int _start; - private readonly int _length; - - public Span(ReadOnlySpan buffer) - : this(0, buffer.Length) - { - } - - private Span(int start, int length) - { - _start = start; - _length = length; - } - - public bool IsEmpty => _length == 0; - - public int Length => _length; - - public int Start => _start; - - public ReadOnlySpan ApplyTo(ReadOnlySpan buffer) - { - return buffer.Slice(_start, _length); - } - - public Span Slice(int start) - { - Debug.Assert(start >= 0 && start <= _length); - - return new Span(_start + start, _length - start); - } - - public Span Slice(int start, int length) - { - Debug.Assert(start >= 0 && start <= _length); - Debug.Assert(length >= 0 && length <= _length - start); - - return new Span(_start + start, length); - } + private Range _element0; } } }