Knapcode.TNetstrings 0.2.0

Prefix Reserved
dotnet add package Knapcode.TNetstrings --version 0.2.0
                    
NuGet\Install-Package Knapcode.TNetstrings -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Knapcode.TNetstrings" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Knapcode.TNetstrings" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Knapcode.TNetstrings" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Knapcode.TNetstrings --version 0.2.0
                    
#r "nuget: Knapcode.TNetstrings, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Knapcode.TNetstrings@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Knapcode.TNetstrings&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Knapcode.TNetstrings&version=0.2.0
                    
Install as a Cake Tool

Knapcode.TNetstrings

This is a .NET library for processing tnetstrings data. TNetstrings is a tagged data format that puts the data type after the data, which means serialization and deserialization often require the data to fully reside in memory to make sense of it.

TNetstrings have 7 data types.

  • Bytes (called "strings" by the specification)
  • Integer
  • Float
  • Boolean
  • Null
  • Dictionary
  • List

The mitmproxy project adds an additional type of UTF-8 strings. This is optionally supported by this library (off by default to be compliant with the tnetstrings specification).

A simple dictionary looks like this:

30:1:a,1:1#2:bb,2:22#3:ccc,3:333#}

This is logically equivalent to the following JSON:

{
    "a": 1,
    "bb": 22,
    "ccc": 333
}

The serialization is done with TNetstringWriter. It writes to an IBufferWriter<byte> instance. One easy way to get an IBufferWriter<byte> instance is with a System.IO.Pipelines.PipeWriter, e.g. PipeWriter.Create(myWriteableStream). PipeWriter implements IBufferWriter<byte>.

The deserialization is done with TNetstringReader. It reads from a System.IO.Pipelines.PipeReader, which can be created from a stream using PipeReader.Create(myReadableStream). Call ReadNextAsync() on the TNetstringReader until false is returned. For each call, the Type and Data properties will be populated. This reader does not recurse into structures like the list or dictionary. Instead, it is meant for iterating over concatenated tnetstrings. To process each record, use TNetStringDataReader or use the ParseData method on TNetstringReader.

Samples

Serialize a dictionary

Serialize a dictionary into a tnetstring.

var bufferWriter = new ArrayBufferWriter<byte>();
var writer = new TNetstringWriter(bufferWriter);
IDictionary dict = new Dictionary<string, int>
{
    { "a", 1 },
    { "bb", 22 },
    { "ccc", 333 }
};
writer.DumpDictionary(dict);
string result = Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
Assert.Equal("30:1:a,1:1#2:bb,2:22#3:ccc,3:333#}", result);

Serialize a list

Serialize a list into a tnetstring.

var bufferWriter = new ArrayBufferWriter<byte>();
var writer = new TNetstringWriter(bufferWriter);
IEnumerable list = new List<string> { "a", "bb", "ccc" };
writer.DumpList(list);
string result = Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
Assert.Equal("15:1:a,2:bb,3:ccc,]", result);

Streaming deserialization

Process concatenated tnetstrings.

using var stream = File.OpenRead(path);
var pipeReader = PipeReader.Create(stream);
using var reader = new TNetstringReader(pipeReader, new TNetstringReaderOptions
{
     // allow the ';' (UTF-8 string) type extension
    AllowUtf8Strings = true,

    // return dictionaries as Dictionary<string, object?>
    DictionaryKeysAsStrings = true, 

    // try to decode all bytes as strings
    ByteStringEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true),
});

while (await reader.ReadNextAsync())
{
    Console.WriteLine($"Type: {reader.Type}, length: {reader.Data.Length}");
    var result = reader.ParseData();
    Console.WriteLine("Parsed the data!");
}

Data deserialization

Once you have a data value in memory, you can use TNetStringDataReader to process it. This is a readonly ref struct and expects only the data portion of the tnetstring (not the length prefix or type suffix).

// no length prefix (implied by the size of the bytes passed in)
// no type suffix (implied by the Read* method called on the reader)
var tnet = "3:foo,3:bar,3:baz,";
var bytes = Encoding.UTF8.GetBytes(tnet);
var reader = new TNetstringDataReader(bytes);
var list = reader.ReadList();
Assert.Equal(new object?[] { "foo", "bar", "baz" }, list.Cast<byte[]>().Select(Encoding.UTF8.GetString).ToList());
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 108 3/21/2026
0.1.0 211 10/14/2025