SynesthesiaDev.Codon.BinaryCodec 2026.220.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package SynesthesiaDev.Codon.BinaryCodec --version 2026.220.1
                    
NuGet\Install-Package SynesthesiaDev.Codon.BinaryCodec -Version 2026.220.1
                    
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="SynesthesiaDev.Codon.BinaryCodec" Version="2026.220.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SynesthesiaDev.Codon.BinaryCodec" Version="2026.220.1" />
                    
Directory.Packages.props
<PackageReference Include="SynesthesiaDev.Codon.BinaryCodec" />
                    
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 SynesthesiaDev.Codon.BinaryCodec --version 2026.220.1
                    
#r "nuget: SynesthesiaDev.Codon.BinaryCodec, 2026.220.1"
                    
#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 SynesthesiaDev.Codon.BinaryCodec@2026.220.1
                    
#: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=SynesthesiaDev.Codon.BinaryCodec&version=2026.220.1
                    
Install as a Cake Addin
#tool nuget:?package=SynesthesiaDev.Codon.BinaryCodec&version=2026.220.1
                    
Install as a Cake Tool

🧬 Codon

Codon is a lightweight codec library for .NET

Codon has five packages:

  • Codon.BinaryBuffer - custom implementation of binary buffer, included in BinaryCodec package
  • Codon.BinaryCodec - for serialization to binary format
  • Codon.Codec - for serialization into any format using transcoders (JSON included)
  • Codon.Optional - Optional class as replacement for nullability because nullable generics SUCK in C#
  • Codon.IniTranscoder - Optional package that includes transcoder for .ini format

Codecs

Lets define a basic codec for Person class: (All examples are using JsonTranscoder but any transcoder may be used)

public record Person(string name, int age, bool isAwesome)
{
    public static readonly StructCodec<Person> Codec = StructCodec.Of
    (
        "name", Codecs.String, p => p.name,
        "age", Codecs.Int, p => p.age,
        "is_awesome", Codecs.Boolean, p => p.isAwesome,
        (name, age, isAwesome) => new Person(name, age, isAwesome) 
    );
}

To Serialize or our Person object we can use:

var person = new Person("Silly Billy", 18, true);

var encoded = Person.Codec.Encode(JsonTranscoder.Instance, person);
Console.WriteLine(encoded.GetRawText()); // {"name":"Silly Billy","age":18,"is_awesome":true}

We can then decode the json back with:

var decoded = Person.Codec.Decode(JsonTranscoder.Instance, encoded);
Console.WriteLine(decoded); // Person { name = Silly Billy, age = 18, isAwesome = True }

You can nest codecs by referencing them in another codec. Lets add PersonalInformation class to our Person class:

public record PersonalInformation(string address, int height, int weight)
{
    public static readonly StructCodec<PersonalInformation> Codec = StructCodec.Of
    (
        "address", Codecs.String, p => p.address,
        "height", Codecs.Int, p => p.height,
        "weight", Codecs.Int, p => p.weight,
        (address, height, weight) => new PersonalInformation(address, height, weight) 
    );
}

Now we can reference it in our Person class just like this:

"personal_information", PersonalInformation.Codec, p => p.personalInformation,
(name, age, someBoolean, personalInformation) => new Person(name, age, someBoolean, personalInformation)

Optional and Default fields

using Codon.Codec;
using Codon.Codec.Transcoder.Transcoders;

public record User(string id, Optional<string> displayName, int level) 
{
    public static readonly StructCodec<User> Codec = StructCodec.Of(
        "id", Codecs.String, u => u.id,
        "display_name", Codecs.String.Optional(), u => u.displayName,
        "level", Codecs.Int.Default(1), u => u.level,
        (id, displayName, level) => new User(id, displayName, level)
    );
};

Missing optional field decodes to Optional.Empty

(Note: Optional class is a custom class for wrapping null values because generics in C# suck and don't pass nullable generics properly)

var json = JsonDocument.Parse("{\"id\":\"u1\"}").RootElement;
var decodedUser = User.Codec.Decode(JsonTranscoder.Instance, json);
Console.WriteLine(decodedUser) // User { id = "u1", displayName = null, level = 1 }

Lists and Maps

var listCodec = Codecs.Int.List(); // ICodec<List<int>>
var mapCodec  = Codecs.String.MapTo(Codecs.Int); // ICodec<Dictionary<string,int>>

var list = new List<int> { 1, 2, 3 };
var map = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };

var encodedList = listCodec.Encode(t, list);
var encodedMap = mapCodec.Encode(t, map);

Enums

enum Color { Red, Green, Blue }

var colorCodec = Codecs.Enum<Color>();
var encodedColor = colorCodec.Encode(t, Color.Green);

Transformative codecs

Wrap one codec to expose values of another type using two conversion functions via the .Transform<Out>(to, from) helper on the inner codec:

// Store an int using an inner string codec (int <-> string)
var intAsString = Codecs.String.Transform<int>(
    to: s => int.Parse(s),
    from: i => i.ToString()
);

var encoded = intAsString.Encode(t, 12345);
var decoded = intAsString.Decode(t, enc); // 12345

Polymorphic Unions (discriminator based)

using Codon.Codec;
using Codon.Codec.Transcoder;
using Codon.Codec.Transcoder.Transcoders;

abstract record Shape;

record Rect(int w, int h) : Shape;

enum Kind { Rect }

// Base codec for Rect
var rectCodec = StructCodec.Of(
    "w", Codecs.Int, r => r.w,
    "h", Codecs.Int, r => r.h,
    (w, h) => new Rect(w, h)
);

// Sometimes you may need a small adapter to upcast StructCodec<Rect> to StructCodec<Shape>
StructCodec<Shape> Upcast(StructCodec<Rect> inner) => new UpcastStructCodec<Shape, Rect>(inner, s => (Rect)s, r => r);

// Build a union codec using an enum discriminator and `.Union(...)` helper
var shapeCodec = ((ICodec<Kind>)Codecs.Enum<Kind>()).Union<Shape>(
    keyField: "kind",
    serializers: kind => kind switch { Kind.Rect => Upcast(rectCodec), _ => throw new InvalidOperationException() },
    keyFunc: shape => shape switch { Rect => Kind.Rect, _ => throw new InvalidOperationException() }
);

// Encode automatically adds the discriminator
var encodedShape = shapeCodec.Encode(JsonTranscoder.Instance, new Rect(3, 4));
var encodedShape = shapeCodec.Decode(JsonTranscoder.Instance, encShape);

Inline nested struct

StructCodec supports an "inline" key that allows embedding a nested struct without an extra object level. Use StructCodec.Inline as the field name (Note: optional/default wrappers are handled when inlined)

public record Outer(int id, Inner inner) 
{
    public static readonly StructCodec<Outer> OuterCodec = StructCodec.Of(
        "id", Codecs.Int, o => o.id,
        StructCodec.Inline, InnerCodec, o => o.inner,
        (id, inner) => new Outer(id, inner)
    );
}

public record Inner(string name) 
{
    public static readonly StructCodec<Inner> InnerCodec = StructCodec.Of(
        "name", Codecs.String, i => i.name,
        name => new Inner(name)
    );
    
}
var example = new Outer(67, new Inner("funny"));
var encoded = Outer.Codec.Encode(JsonTranscoder.Instance, example);

This would be encoded as following:

{
  "id": 67,
  "name": "Funny"
}

Transcoders

  • The examples use the JSON transcoder (JsonTranscoder.Instance), but any transport can be supported by implementing ITranscoder<T>.
  • StructCodec encodes into the transcoder’s concept of a map/object and decodes from it using provided field definitions.
  • Optional and Default wrappers help you model absent fields and fallback values.

Versioned Struct Codecs

Versioned struct codecs (VersionedStructCodec<R>) tracks schema versions and automatically applies migrations:

private const string old_person_json = "{\"display_name\":\"Synesthesia Dev\", \"is_awesome\":true}";

public record Person(string Name, int Age, Optional<bool> IsAwesome)
{
    private static readonly StructCodec<Person> codec = StructCodec.Of (
        "name", Codecs.String, p => p.Name,
        "age", Codecs.Int, p => p.Age,
        "is_awesome", Codecs.Boolean.Optional(), p => p.IsAwesome,
        (name, age, someBoolean) => new Person(name, age, someBoolean) 
    );
    
    // schema version 1: added "age" field
    // schema version 2: renamed "display_name" to just "name"
    
    public static readonly VersionedStructCodec<Person> VERSIONED_CODEC = new VersionedStructCodec<Person>()
    {
        CurrentSchemaVersion = 2,
        InnerCodec = Person.codec,
        SchemaMigrationRegistry = SchemaMigrationRegistry.Builder()
            // Specify for what transcoder type/format this migration is
            .For<JsonElement>(migrations =>
            {
                // migration to version 1: ensure "age" exists
                migrations.Add(1, (transcoder, _, output) => output.Put("age", transcoder.EncodeInt(0)));
                // migration to version 2: copy "display_name" -> "name"
                migrations.Add(2, (transcoder, input, output) =>
                {
                    var name = transcoder.DecodeString(input.GetValue("display_name"));
                    output.Put("name", transcoder.EncodeString(name));
                });
            })
    };
}

See the test suite under Codon.Tests for broader coverage (lists, maps, enums, unions, forward refs, array helpers, etc.).

BinaryCodecs

BinaryCodecs work with a BinaryBuffer and have a similar API to normal codecs (Optional, Default, List, MapTo, Transform, Enum, Recursive, and composite Of helpers).

Quick roundtrip with primitives:

using Codon.Binary;
using Codon.Buffer;

var buf = new BinaryBuffer();

// Write
BinaryCodec.Int.Write(buf, 42);
BinaryCodec.String.Write(buf, "hello");
BinaryCodec.Boolean.Write(buf, true);

// Read back in the same order
var int = BinaryCodec.Int.Read(buf);       // 42
var string = BinaryCodec.String.Read(buf); // "hello"
var bool = BinaryCodec.Boolean.Read(buf);  // true

Lists, maps, optionals, enums:

// List and Dictionary helpers
var listCodec = BinaryCodec.Int.List(); // IBinaryCodec<List<int>>
var mapCodec  = BinaryCodec.String.MapTo(BinaryCodec.Int); // IBinaryCodec<Dictionary<string,int>>

var list = new List<int> { 1, 2, 3 };
listCodec.Write(buffer, list);
var listBack = listCodec.Read(buffer);

// Optional
var optInt = BinaryCodec.Int.Optional();
optInt.Write(buffer, Optional.Of(123));
var readOpt = optInt.Read(buffer); // present 123

// Enums
enum Color { Red, Green, Blue }
var colorCodec = BinaryCodec.Enum<Color>();
colorCodec.Write(buffer, Color.Green);
var color = colorCodec.Read(buffer); // Color.Green

Composite codecs (struct-like) using Of(...):

public record Person(string name, int age, bool active)
{
    public static readonly IBinaryCodec<Person> Codec = BinaryCodec.Of(
        BinaryCodec.String, p => p.name,
        BinaryCodec.Int, p => p.age,
        BinaryCodec.Boolean, p => p.active,
        (name, age, active) => new Person(name, age, active)
    );
}

Person.Codec.Write(buffer, new Person("Alice", 30, true));
var person = Person.Codec.Read(buffer);

Transform between types:

// Store a string as its length using the inner Int codec
var lengthAsString = BinaryCodec.Int.Transform(
    from: (string s) => s.Length,
    to:   (int n)    => new string('x', n)
);

lengthAsString.Write(buffer, "abcde");
var restored = lengthAsString.Read(buffer); //

Recursive structures are supported via BinaryCodec.Recursive(self => ...):

public record Node(string name, List<Node> children)
{
    public static readonly IBinaryCodec<Node> Codec = BinaryCodec.Recursive<Node>(self =>
        BinaryCodec.Of(
            BinaryCodec.String, n => n.name,
            self.List(),        n => n.children,
            (name, children) => new Node(name, children)
        )
    );
}

BinaryBuffer has helpers like ToArray()/FromArray and ReaderIndex/WriterIndex if you need more control over IO.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  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 (1)

Showing the top 1 NuGet packages that depend on SynesthesiaDev.Codon.BinaryCodec:

Package Downloads
SynesthesiaDev.Codon.Codon

A .NET Codec library that can both serialize into binary format and any other format via custom transcoders

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.220.5 34 2/20/2026
2026.220.1 30 2/20/2026
1.1.1 118 2/9/2026
1.1.0 97 2/9/2026
1.0.1 108 1/3/2026
1.0.0 126 12/12/2025