Utf8BencodeReader Struct
Definition
Provides a high-performance, forward-only, allocation-light reader for Bencode (BEP 3) bytes. The reader is a
ref struct, so it lives on the stack and cannot be boxed or captured; pass it by
ref to thread it through a converter.
public ref struct Utf8BencodeReader
- Inherited Members
Remarks
A call to Read() advances to the next token and reports it through TokenType. Integer and byte-string values are decoded on demand through GetInt64(), GetUInt64(), ValueSpan, and GetString(). Integer tokens span the union of the signed and unsigned 64-bit ranges [MinValue, MaxValue ]; values above MaxValue are readable only through GetUInt64(). The reader enforces the canonical Bencode grammar - integers without leading zeros or negative zero, byte-string lengths without leading zeros, dictionary keys that are byte strings in strictly ascending bytewise order, balanced containers, and a single root value with no trailing bytes - raising BencodeFormatException on any departure from that canonical form.
Real-world documents produced by older encoders occasionally carry unsorted or duplicate dictionary keys. The opt-in AllowUnsortedKeys and AllowDuplicateKeys options relax those two rules independently; every other grammar rule remains enforced.
// Read "d3:cowi42ee" -> dictionary { "cow": 42 }.
ReadOnlySpan<byte> bytes = "d3:cowi42ee"u8;
var reader = new Utf8BencodeReader(bytes);
while (reader.Read())
{
switch (reader.TokenType)
{
case BencodeTokenType.PropertyName:
Console.Write($"{reader.GetString()} = ");
break;
case BencodeTokenType.Integer:
Console.WriteLine(reader.GetInt64());
break;
}
}
Constructors
Utf8BencodeReader(ReadOnlySpan<byte>, BencodeReaderOptions)
Initializes a new instance of the Utf8BencodeReader struct over the supplied bytes using the supplied options.
public Utf8BencodeReader(ReadOnlySpan<byte> data, BencodeReaderOptions options)
Parameters
dataReadOnlySpan<byte>The Bencode source bytes.
optionsBencodeReaderOptionsThe reader options controlling the maximum nesting depth and key leniency.
Remarks
A MaxDepth of zero or less selects the default maximum depth of 64, and a larger value is clamped to Bodu.Text.Bencode.BencodeLimits.AbsoluteMaxDepth; a document nested deeper than the effective limit throws BencodeFormatException.
Utf8BencodeReader(ReadOnlySpan<byte>, int)
Initializes a new instance of the Utf8BencodeReader struct over the supplied bytes.
public Utf8BencodeReader(ReadOnlySpan<byte> data, int maxDepth = 64)
Parameters
dataReadOnlySpan<byte>The Bencode source bytes.
maxDepthintThe maximum permitted container nesting depth.
Remarks
The value is clamped to Bodu.Text.Bencode.BencodeLimits.AbsoluteMaxDepth so that an unbounded configured value cannot drive the reader into a StackOverflowException on a deeply nested document.
Exceptions
- ArgumentOutOfRangeException
Thrown when
maxDepthis not positive.
Properties
BytesConsumed
Gets the number of bytes consumed so far.
public readonly int BytesConsumed { get; }
Property Value
- int
The read position.
CurrentDepth
Gets the current container nesting depth.
public readonly int CurrentDepth { get; }
Property Value
- int
The depth, where zero is the document root.
TokenStartIndex
Gets the byte offset within the source where the current token begins. For a byte string or property name the offset addresses the length prefix, not the content.
public readonly int TokenStartIndex { get; }
Property Value
- int
The current token's start offset, or zero before the first token has been read.
TokenType
Gets the kind of the current token.
public readonly BencodeTokenType TokenType { get; }
Property Value
- BencodeTokenType
The current token kind.
ValueSpan
Gets the raw content bytes of the current byte-string or property-name token.
public readonly ReadOnlySpan<byte> ValueSpan { get; }
Property Value
- ReadOnlySpan<byte>
The byte-string content.
Methods
CopyString(Span<byte>)
Copies the current byte-string or property-name token's raw content into the supplied destination.
public readonly int CopyString(Span<byte> destination)
Parameters
Returns
- int
The number of bytes written to
destination.
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
- ArgumentException
Thrown when
destinationis shorter than the token's content.
CopyString(Span<char>)
Decodes the current byte-string or property-name token's content as UTF-8 text into the supplied destination.
public readonly int CopyString(Span<char> destination)
Parameters
Returns
- int
The number of characters written to
destination.
Remarks
Decoding matches GetString(): byte sequences that are not valid UTF-8 are replaced with U+FFFD rather than rejected. Use CopyString(Span<byte>) to recover binary content losslessly.
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
- ArgumentException
Thrown when
destinationis shorter than the decoded character count.
GetBytes()
Copies the current byte-string or property-name token's content to a new array.
public readonly byte[] GetBytes()
Returns
- byte[]
The byte-string content.
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
GetInt32()
Reads the current integer token as a 32-bit signed integer.
public readonly int GetInt32()
Returns
- int
The integer value.
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
- BencodeFormatException
Thrown when the integer token's value is outside the int range.
GetInt64()
Reads the current integer token as a 64-bit signed integer.
public readonly long GetInt64()
Returns
- long
The integer value.
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
- BencodeFormatException
Thrown when the integer token's value exceeds MaxValue; use GetUInt64() to read values in the upper unsigned 64-bit range.
GetString()
Decodes the current byte-string or property-name token as UTF-8 text.
public readonly string GetString()
Returns
- string
The decoded string.
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
GetUInt64()
Reads the current integer token as a 64-bit unsigned integer, accepting any value in [0, MaxValue ].
public readonly ulong GetUInt64()
Returns
- ulong
The unsigned integer value.
Remarks
Bencode integers are arbitrary-precision per BEP 3, so a document may carry a value between MaxValue and MaxValue that GetInt64() cannot represent; this accessor reads such values without loss.
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
- BencodeFormatException
Thrown when the integer token's value is negative.
Read()
Advances the reader to the next token.
public bool Read()
Returns
Exceptions
- BencodeFormatException
Thrown when the bytes are not valid Bencode.
Skip()
Skips the current value, including the entire subtree when the reader is on a container start. On a property name the reader first advances to the property's value and then skips it.
public void Skip()
Exceptions
- BencodeFormatException
Thrown when the skipped bytes are not valid Bencode.
TryGetInt32(out int)
Attempts to read the current integer token as a 32-bit signed integer.
public readonly bool TryGetInt32(out int value)
Parameters
Returns
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
TryGetInt64(out long)
Attempts to read the current integer token as a 64-bit signed integer.
public readonly bool TryGetInt64(out long value)
Parameters
Returns
- bool
true when the current integer token fits the signed 64-bit range; false when it exceeds MaxValue and is therefore readable only through GetUInt64().
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
TryGetUInt64(out ulong)
Attempts to read the current integer token as a 64-bit unsigned integer.
public readonly bool TryGetUInt64(out ulong value)
Parameters
Returns
- bool
true when the current integer token is non-negative; false when it is negative and therefore not representable as ulong.
Exceptions
- InvalidOperationException
Thrown when the current token is not an integer.
TrySkip()
Attempts to skip the current value.
public bool TrySkip()
Returns
Remarks
This reader has no streaming mode in which a value could end partway through a buffer, so the method is equivalent to Skip() and exists for source compatibility with callers written against a try-pattern surface.
Exceptions
- BencodeFormatException
Thrown when the skipped bytes are not valid Bencode.
ValueTextEquals(ReadOnlySpan<byte>)
Compares the current byte-string or property-name token's content to the supplied UTF-8 bytes without allocating.
public readonly bool ValueTextEquals(ReadOnlySpan<byte> utf8Text)
Parameters
utf8TextReadOnlySpan<byte>The UTF-8 bytes to compare against.
Returns
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
ValueTextEquals(ReadOnlySpan<char>)
Compares the current byte-string or property-name token's content to the UTF-8 encoding of the supplied characters.
public readonly bool ValueTextEquals(ReadOnlySpan<char> text)
Parameters
textReadOnlySpan<char>The characters to compare against.
Returns
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
ValueTextEquals(string?)
Compares the current byte-string or property-name token's content to the UTF-8 encoding of the supplied string.
public readonly bool ValueTextEquals(string? text)
Parameters
Returns
Remarks
A null argument behaves as the empty string and therefore matches an empty byte string.
Exceptions
- InvalidOperationException
Thrown when the current token is not a byte string or property name.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |