Table of Contents

Utf8BencodeReader Struct

Definition

Namespace
Bodu.Text.Bencode.Reader
Assembly
Bodu.Text.Bencode.dll
Package
Bodu.Text.Bencode 1.0.0
Source
Utf8BencodeReader.cs

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

data ReadOnlySpan<byte>

The Bencode source bytes.

options BencodeReaderOptions

The 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

data ReadOnlySpan<byte>

The Bencode source bytes.

maxDepth int

The 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 maxDepth is 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

destination Span<byte>

The buffer that receives the raw content bytes.

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 destination is 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

destination Span<char>

The buffer that receives the decoded characters.

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 destination is 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

bool

true when a token was read; false at the end of the document.

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

value int

When this method returns true, the integer value; otherwise zero.

Returns

bool

true when the current integer token fits the int range; otherwise false.

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

value long

When this method returns true, the integer value; otherwise zero.

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

value ulong

When this method returns true, the unsigned integer value; otherwise zero.

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

bool

true always, because the reader operates over a complete buffer.

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

utf8Text ReadOnlySpan<byte>

The UTF-8 bytes to compare against.

Returns

bool

true when the token's raw content equals utf8Text byte for byte; otherwise false.

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

text ReadOnlySpan<char>

The characters to compare against.

Returns

bool

true when the token's raw content equals the UTF-8 encoding of text; otherwise false.

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

text string

The string to compare against, which may be null.

Returns

bool

true when the token's raw content equals the UTF-8 encoding of text; otherwise false.

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

ProductVersions
.NET8, 10