BinaryStruct 0.0.1

dotnet add package BinaryStruct --version 0.0.1                
NuGet\Install-Package BinaryStruct -Version 0.0.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="BinaryStruct" Version="0.0.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BinaryStruct --version 0.0.1                
#r "nuget: BinaryStruct, 0.0.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.
// Install BinaryStruct as a Cake Addin
#addin nuget:?package=BinaryStruct&version=0.0.1

// Install BinaryStruct as a Cake Tool
#tool nuget:?package=BinaryStruct&version=0.0.1                

BinaryStruct

Declarative data structures that allow for binary parsing and building.
Heavily based on the base functions of the python construct library.

Examples

General Usage

using static BinaryStruct.ParserBuilder;

var example = new Struct(
    Int16ub("size"),
    Bytes("data", ctx => ctx["size"]),
    Int8ub("count"),
    Array("items", Int16ul(string.Empty), ctx => ctx["count"])
);

// Input data: 001000000000000000000000000000000000040100020003000400

var result = example.Parse(new byte[] { ... });
// OR
// using var stream = File.OpenRead(args[0]);
// var result = example.Parse(stream);

// Results in:
/*
 *  new Dictionary<string, object>{
 *      { "size", (ushort)16 },
 *      { "data", new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
 *      { "count", (byte)4 },
 *      { "items", new List<object>{ (ushort)1, (ushort)2, (ushort)3, (ushort)4 },
 *  }
 */

var bytes = example.Build(result);
// Output data: 001000000000000000000000000000000000040100020003000400

Fields

IntField

var example = new Struct(
    Int8ub("Int8ub"),   // big-endian byte
    Int8ul("Int8ul"),   // little-endian byte
    Int8sb("Int8sb"),   // big-endian sbyte
    Int8sl("Int8sl"),   // little-endian sbyte
    Int16ub("Int16ub"), // big-endian ushort
    Int16ul("Int16ul"), // little-endian ushort
    Int16sb("Int16sb"), // big-endian short
    Int16sl("Int16sl"), // little-endian short
    Int32ub("Int32ub"), // big-endian uint
    Int32ul("Int32ul"), // little-endian uint
    Int32sb("Int32sb"), // big-endian int
    Int32sl("Int32sl"), // little-endian int
    Int64ub("Int64ub"), // big-endian ulong
    Int64ul("Int64ul"), // little-endian ulong
    Int64sb("Int64sb"), // big-endian long
    Int64sl("Int64sl")  // little-endian long
);

BytesField

var example = new Struct(
    Bytes("data1", 16), // static length
    Bytes("data2", ctx => ctx["Int8sl"]) // get length from field named 'Int8sl'
);

ConstField

var example = new Struct(
    Const("const", "CONST"u8.ToArray()) // always expects 'CONST'
);

StringField

var example = new Struct(
    ASCIIString("asciiString1", 16), // static length ASCII string
    ASCIIString("asciiString2", ctx => ctx["Int8sl"]), // get length from field named 'Int8sl'
    UTF8String("utf8String1", 16), // static length UTF-8 string
    UTF8String("utf8String2", ctx => ctx["Int8sl"]), // get length from field named 'Int8sl'
    UTF16String("utf16String1", 18), // static length UTF-16/Unicode string
    UTF16String("utf16String2", ctx => (sbyte)ctx["Int8sl"] + 2) // cast for addition, etc...
);

ArrayField

var example = new Struct(
    Array("array", Int16ub(string.Empty), ctx => ctx["Int8sl"]), // get count from field named 'Int8sl'
    Array("array2", Int16ub(string.Empty), 2) // static count
);

SwitchField

var example = new Struct(
    Switch("switch", ctx => ctx["Int8sl"], i => i switch // switch based on value of field named 'Int8sl'
    {
        1 => Int32ub(string.Empty),
        _ => throw new ArgumentOutOfRangeException(nameof(i), i, null)
    }),
    Switch("switch2", 2, i => i switch // static value
    {
        1 => Int32ub(string.Empty),
        _ => Bytes(string.Empty, 4)
    })
);

ConditionalField

var example = new Struct(
    IfThenElse("ifThenElse", ctx => ctx["Int8sl"], Bytes(string.Empty, 6), Bytes(string.Empty, 4)), // basically ctx["Int8sl"] ? Bytes(string.Empty, 6) : Bytes(string.Empty, 4))
    IfThenElse("ifThenElse2", false, Bytes(string.Empty, 6), Bytes(string.Empty, 4)), // basically ctx["Int8sl"] ? Bytes(string.Empty, 6) : Bytes(string.Empty, 4))
    If("if", ctx => ctx["Int8sl"], Bytes(string.Empty, 6)), // writes nothing and returns new object() if ctx["Int8sl"] is false
    If("if2", false, Bytes(string.Empty, 4)) // writes nothing and returns new object()
);

RangeField

var example = new Struct(
    Range("range", Int32ub(string.Empty), 1, 2) // will repeat Int32ub two times but only throws an error if it crashes earlier and has read less than one item
    Range("range", Int32ub(string.Empty), 1, ctx => ctx["Int16ub"]) // variable counts
    Range("range", Int32ub(string.Empty), ctx => ctx["Int8sl"], 2) // variable counts
    Range("range", Int32ub(string.Empty), ctx => ctx["Int8sl"], ctx => ctx["Int16ub"]) // variable counts
    GreedyRange("greedy", Const(string.Empty, "string"u8.ToArray())) // reads as much as possible until it crashes (errors are catched, so debugging is difficult)
);

StructField

var example = new Struct(
    Child("subStruct", SubStruct) // include another Struct
);
// Recursiveness
private static readonly Struct Record = new(
    Int16ub("flags"),
    Int16ub("type"),
    Int32ub("length"),
    Switch("data", ctx => ctx["type"], i => i switch 
    {
        1 => Child(string.Empty, SubStruct1),
        2 => Child(string.Empty, SubStruct2),
        _ => Child(string.Empty, () => Record!) // References itself (must be a lambda)
    })
);
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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on BinaryStruct:

Package Downloads
csplayready

C# implementation of Microsoft's Playready DRM CDM (Content Decryption Module)

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.0.1 120 1/3/2025