Beskar.Memory.Serialization
1.6.2
dotnet add package Beskar.Memory.Serialization --version 1.6.2
NuGet\Install-Package Beskar.Memory.Serialization -Version 1.6.2
<PackageReference Include="Beskar.Memory.Serialization" Version="1.6.2" />
<PackageVersion Include="Beskar.Memory.Serialization" Version="1.6.2" />
<PackageReference Include="Beskar.Memory.Serialization" />
paket add Beskar.Memory.Serialization --version 1.6.2
#r "nuget: Beskar.Memory.Serialization, 1.6.2"
#:package Beskar.Memory.Serialization@1.6.2
#addin nuget:?package=Beskar.Memory.Serialization&version=1.6.2
#tool nuget:?package=Beskar.Memory.Serialization&version=1.6.2
Beskar.Memory.Serialization
A modern, suite-integrated, zero-allocation, ultra-high-performance binary serialization engine for .NET. By combining Roslyn source generation, C# 12 static abstract interface members, and variable-length integer compaction, Beskar.Memory.Serialization achieves blazing-fast execution speeds and near-zero garbage collection overhead.
Key Features
- Zero-Overhead Static Abstract Interfaces: Built on
ISerializer<T>with static abstract interface methods, completely bypassing virtual dispatch and interface object allocation overhead. Fully compatible with the C# 12allows ref structanti-constraint. - Incremental Roslyn Source Generator (
[BeskarObject]): Automatically generates highly-optimized serializers for your custom classes and structs at compile time. Eliminates runtime reflection and startup latency entirely. - Variable-Length Integer Encoding (
VarInteger):- Uses LEB128 Varint compaction for unsigned types (
uint,ulong) and length headers (arrays, lists, strings). - Employs ZigZag mapping for signed types (
int,long) to compact small negative numbers (e.g.,-1encodes into1byte instead of10bytes).
- Uses LEB128 Varint compaction for unsigned types (
- Comprehensive Type Support: Out-of-the-box support for primitive types, enums, nullables,
Guid,DateTime,DateTimeOffset,TimeSpan,DateOnly,TimeOnly,Uri, collections (T[],List<T>), and polymorphic unions ([BeskarUnion]). - Ultra-Fast Stream & Memory Pipelines: Integrates deeply with modern high-performance .NET memory types:
BufferWriter<byte>,SequenceReader<byte>,ReadOnlySequence<byte>, and stack-allocated spans.
Architecture Overview
At the heart of the library is the ISerializer<T> interface:
public interface ISerializer<T> : ISerializer
where T : allows ref struct
{
public static abstract int Write(ref BufferWriter<byte> writer, scoped in T value);
public static abstract bool TryRead(ref SequenceReader<byte> reader, [MaybeNullWhen(false)] out T value);
public static abstract int CalculateByteLength(scoped in T value);
}
By leveraging static abstract methods, the compiler resolves the serializer call paths statically at compile time, allowing aggressive inlining and zero-overhead dispatch.
Getting Started
1. Annotate your Data Objects
Decorate your classes or structs with [BeskarObject] and declare them as partial. Use [BeskarOrder(index)] to define a deterministic serialization order:
using Beskar.Memory.Serialization.Attributes;
[BeskarObject]
public partial struct PlayerPosition
{
[BeskarOrder(0)]
public int PlayerId { get; set; }
[BeskarOrder(1)]
public float X { get; set; }
[BeskarOrder(2)]
public float Y { get; set; }
[BeskarOrder(3)]
public string? StatusMessage { get; set; }
}
2. Standard Usage (BeSerializer)
The BeSerializer static utility class provides highly optimized, convenient methods for serialization and deserialization:
Serialization
var position = new PlayerPosition
{
PlayerId = 1337,
X = 12.5f,
Y = 88.2f,
StatusMessage = "Active"
};
// 1. Serialize to a fresh byte array (uses a 256-byte stackalloc buffer for single-pass fast paths)
byte[] bytes = BeSerializer.Serialize(position);
// 2. Serialize directly into an existing Span<byte> (zero-allocation)
Span<byte> buffer = stackalloc byte[128];
int bytesWritten = BeSerializer.Serialize(position, buffer);
// 3. Serialize into a high-performance BufferWriter<byte>
var writer = new BufferWriter<byte>(buffer);
BeSerializer.Serialize(position, ref writer);
Deserialization
// 1. Deserialize from a byte array or ReadOnlySpan<byte>
PlayerPosition player = BeSerializer.Deserialize<PlayerPosition>(bytes);
// 2. Try-deserialization style (defensive parsing)
if (BeSerializer.TryDeserialize<PlayerPosition>(bytes, out var result))
{
// Use deserialized object...
}
Versioning & Polymorphic Unions
You can easily handle polymorphism using the [BeskarUnion] attribute, which automatically includes a tag prefix to safely multiplex and demultiplex derived or alternative types:
[BeskarObject]
[BeskarUnion(1, typeof(TextMessage))]
[BeskarUnion(2, typeof(ImageMessage))]
public abstract partial class NetworkMessage;
[BeskarObject]
public partial class TextMessage : NetworkMessage
{
[BeskarOrder(0)]
public string Content { get; set; } = string.Empty;
}
[BeskarObject]
public partial class ImageMessage : NetworkMessage
{
[BeskarOrder(0)]
public byte[] ImageData { get; set; } = Array.Empty<byte>();
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Beskar.Memory (>= 1.6.2)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Beskar.Memory.Serialization:
| Package | Downloads |
|---|---|
|
Beskar.Experiments
Package Description |
|
|
Beskar.Memory.Benchmarks.Live
Package Description |
|
|
Beskar.Memory.Benchmarks
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.