Table of Contents

Utf8BencodeWriter Struct

Definition

Namespace
Bodu.Text.Bencode.Writer
Assembly
Bodu.Text.Bencode.dll
Package
Bodu.Text.Bencode 1.0.0
Source
Utf8BencodeWriter.cs

Provides a forward-only writer that emits canonical Bencode (BEP 3) bytes to an IBufferWriter<T>. Because the grammar requires dictionary keys in ascending bytewise order, the writer buffers each dictionary's entries and sorts them when the dictionary is closed; values at the root and inside lists stream directly to the destination.

public ref struct Utf8BencodeWriter
Inherited Members

Remarks

The writer is a ref struct whose mutable state lives in shared managed buffers, so a copy taken by value continues to write to the same output. Booleans, floating-point values, and date-times have no Bencode representation and must be reduced to an integer or byte string by a converter before they are written.

The writer validates the call sequence against the canonical grammar: a property name may only be written inside an open dictionary, every dictionary value must follow a property name, container ends must match the open container kind, a dictionary containing duplicate keys is rejected when it is closed, and a second root value is rejected unless AllowMultipleRootValues is set.

Scalars and lists written outside any dictionary are emitted to the destination as they are written; bytes that belong to an open dictionary are held in that dictionary's buffer until it closes, because the canonical key order is only known at that point. A consequence of streaming is that a write failing partway through a document leaves the bytes already emitted in the destination - discard the destination when any write throws, and assert CurrentDepth is zero before consuming it.

var output = new ArrayBufferWriter<byte>();
var writer = new Utf8BencodeWriter(output);

writer.WriteStartDictionary();
writer.WriteString("cow", "moo");   // keys are sorted on close
writer.WriteInteger("age", 42);
writer.WriteEndDictionary();

// output.WrittenSpan now holds canonical "d3:agei42e3:cow3:mooe".

Constructors

Utf8BencodeWriter(IBufferWriter<byte>)

Initializes a new instance of the Utf8BencodeWriter struct.

public Utf8BencodeWriter(IBufferWriter<byte> output)

Parameters

output IBufferWriter<byte>

The destination buffer writer.

Exceptions

ArgumentNullException

Thrown when output is null.

Utf8BencodeWriter(IBufferWriter<byte>, BencodeWriterOptions)

Initializes a new instance of the Utf8BencodeWriter struct using the supplied options.

public Utf8BencodeWriter(IBufferWriter<byte> output, BencodeWriterOptions options)

Parameters

output IBufferWriter<byte>

The destination buffer writer.

options BencodeWriterOptions

The writer options controlling the maximum nesting depth and root-value policy.

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 so that an unbounded configured value cannot drive the writer into a StackOverflowException. Opening a list or dictionary past that depth throws BencodeSerializationException.

Exceptions

ArgumentNullException

Thrown when output is null.

Properties

CurrentDepth

Gets the current container nesting depth.

public readonly int CurrentDepth { get; }

Property Value

int

The number of open containers, where zero means the writer is at the document root.

Remarks

A document is complete only when the depth has returned to zero: an unclosed dictionary's bytes never reach the destination, and an unclosed list leaves the output without its terminating e. Callers driving the writer manually can assert this property is zero before consuming the destination.

Options

Gets the customizations the writer was created with.

public readonly BencodeWriterOptions Options { get; }

Property Value

BencodeWriterOptions

The effective options, with MaxDepth carrying the resolved value rather than a zero placeholder.

Methods

WriteByteString(ReadOnlySpan<byte>)

Writes a byte-string value.

public readonly void WriteByteString(ReadOnlySpan<byte> value)

Parameters

value ReadOnlySpan<byte>

The byte-string content.

Exceptions

InvalidOperationException

Thrown when the value is written directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

WriteByteString(ReadOnlySpan<byte>, ReadOnlySpan<byte>)

Writes a property name and a byte-string value in one call.

public readonly void WriteByteString(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)

Parameters

name ReadOnlySpan<byte>

The key bytes.

value ReadOnlySpan<byte>

The byte-string content.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteByteString(string, ReadOnlySpan<byte>)

Writes a property name and a byte-string value in one call.

public readonly void WriteByteString(string name, ReadOnlySpan<byte> value)

Parameters

name string

The key text.

value ReadOnlySpan<byte>

The byte-string content.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteEndDictionary()

Writes the end of the current dictionary, emitting its entries in ascending bytewise key order.

public readonly void WriteEndDictionary()

Exceptions

InvalidOperationException

Thrown when no container is open, when the currently open container is not a dictionary, or when a property name is still awaiting its value.

BencodeSerializationException

Thrown when the dictionary contains more than one entry for the same key, which canonical Bencode forbids.

WriteEndList()

Writes the end of the current list.

public readonly void WriteEndList()

Exceptions

InvalidOperationException

Thrown when no container is open, or when the currently open container is not a list.

WriteInteger(long)

Writes an integer value.

public readonly void WriteInteger(long value)

Parameters

value long

The integer value.

Exceptions

InvalidOperationException

Thrown when the value is written directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

WriteInteger(ReadOnlySpan<byte>, long)

Writes a property name and an integer value in one call.

public readonly void WriteInteger(ReadOnlySpan<byte> name, long value)

Parameters

name ReadOnlySpan<byte>

The key bytes.

value long

The integer value.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteInteger(ReadOnlySpan<byte>, ulong)

Writes a property name and an unsigned integer value in one call, permitting the full ulong range.

public readonly void WriteInteger(ReadOnlySpan<byte> name, ulong value)

Parameters

name ReadOnlySpan<byte>

The key bytes.

value ulong

The unsigned integer value.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteInteger(string, long)

Writes a property name and an integer value in one call.

public readonly void WriteInteger(string name, long value)

Parameters

name string

The key text.

value long

The integer value.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteInteger(string, ulong)

Writes a property name and an unsigned integer value in one call, permitting the full ulong range.

public readonly void WriteInteger(string name, ulong value)

Parameters

name string

The key text.

value ulong

The unsigned integer value.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteInteger(ulong)

Writes an unsigned integer value, permitting the full ulong range.

public readonly void WriteInteger(ulong value)

Parameters

value ulong

The unsigned integer value.

Remarks

Bencode integers are arbitrary-precision in BEP 3, so values between MaxValue and MaxValue are valid documents even though they exceed the writer's signed 64-bit overload. A reader consuming such a value must use GetUInt64() rather than GetInt64().

Exceptions

InvalidOperationException

Thrown when the value is written directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

WritePropertyName(ReadOnlySpan<byte>)

Writes the name of the dictionary key whose value follows.

public readonly void WritePropertyName(ReadOnlySpan<byte> name)

Parameters

name ReadOnlySpan<byte>

The key bytes.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WritePropertyName(ReadOnlySpan<char>)

Writes the name of the dictionary key whose value follows, encoding the characters as UTF-8.

public readonly void WritePropertyName(ReadOnlySpan<char> name)

Parameters

name ReadOnlySpan<char>

The key text.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WritePropertyName(string)

Writes the name of the dictionary key whose value follows, encoding the name as UTF-8.

public readonly void WritePropertyName(string name)

Parameters

name string

The key text.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteRawValue(ReadOnlySpan<byte>, bool)

Writes a pre-encoded Bencode value verbatim. Supports round-tripping verified slices such as a torrent's info dictionary without re-encoding.

public readonly void WriteRawValue(ReadOnlySpan<byte> value, bool skipInputValidation = false)

Parameters

value ReadOnlySpan<byte>

The complete, already-encoded Bencode value bytes.

skipInputValidation bool

true to write the bytes without verifying they form a single complete Bencode value.

Remarks

Validation parses value with a standalone Utf8BencodeReader using the default maximum depth; the payload's nesting is not counted against this writer's configured MaxDepth. When validation is skipped the caller is responsible for the bytes being canonical - non-canonical bytes produce a document this library's reader rejects.

Exceptions

BencodeFormatException

Thrown when validation is enabled and value is not exactly one complete, canonical Bencode value.

InvalidOperationException

Thrown when the value is written directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

WriteStartDictionary()

Writes the start of a dictionary.

public readonly void WriteStartDictionary()

Remarks

No bytes are emitted until the dictionary closes: entries must be reordered into ascending bytewise key order, so the dictionary's content accumulates in a private buffer that WriteEndDictionary() flushes.

Exceptions

InvalidOperationException

Thrown when the dictionary is opened directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

BencodeSerializationException

Thrown when opening the dictionary would exceed the configured maximum nesting depth.

WriteStartDictionary(ReadOnlySpan<byte>)

Writes a property name and the start of a dictionary as its value.

public readonly void WriteStartDictionary(ReadOnlySpan<byte> name)

Parameters

name ReadOnlySpan<byte>

The key bytes.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

BencodeSerializationException

Thrown when opening the dictionary would exceed the configured maximum nesting depth.

WriteStartDictionary(string)

Writes a property name and the start of a dictionary as its value, combining WritePropertyName(string) and WriteStartDictionary().

public readonly void WriteStartDictionary(string name)

Parameters

name string

The key text.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

BencodeSerializationException

Thrown when opening the dictionary would exceed the configured maximum nesting depth.

WriteStartList()

Writes the start of a list.

public readonly void WriteStartList()

Exceptions

InvalidOperationException

Thrown when the list is opened directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

BencodeSerializationException

Thrown when opening the list would exceed the configured maximum nesting depth.

WriteStartList(ReadOnlySpan<byte>)

Writes a property name and the start of a list as its value.

public readonly void WriteStartList(ReadOnlySpan<byte> name)

Parameters

name ReadOnlySpan<byte>

The key bytes.

Exceptions

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

BencodeSerializationException

Thrown when opening the list would exceed the configured maximum nesting depth.

WriteStartList(string)

Writes a property name and the start of a list as its value, combining WritePropertyName(string) and WriteStartList().

public readonly void WriteStartList(string name)

Parameters

name string

The key text.

Exceptions

ArgumentNullException

Thrown when name is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

BencodeSerializationException

Thrown when opening the list would exceed the configured maximum nesting depth.

WriteString(ReadOnlySpan<byte>, string)

Writes a property name and a string value in one call, encoding the value as UTF-8.

public readonly void WriteString(ReadOnlySpan<byte> name, string value)

Parameters

name ReadOnlySpan<byte>

The key bytes.

value string

The string value.

Exceptions

ArgumentNullException

Thrown when value is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

WriteString(string)

Writes a string value, encoding it as a UTF-8 byte string.

public readonly void WriteString(string value)

Parameters

value string

The string value.

Exceptions

ArgumentNullException

Thrown when value is null.

InvalidOperationException

Thrown when the value is written directly inside a dictionary before a property name has been written, or when a complete root value has already been written and AllowMultipleRootValues is not set.

WriteString(string, string)

Writes a property name and a string value in one call, encoding both as UTF-8.

public readonly void WriteString(string name, string value)

Parameters

name string

The key text.

value string

The string value.

Exceptions

ArgumentNullException

Thrown when name or value is null.

InvalidOperationException

Thrown when the currently open container is not a dictionary, or when a previously written property name is still awaiting its value.

Applies to

ProductVersions
.NET8, 10