Chronicler.Core.Lean
0.2.0
dotnet add package Chronicler.Core.Lean --version 0.2.0
NuGet\Install-Package Chronicler.Core.Lean -Version 0.2.0
<PackageReference Include="Chronicler.Core.Lean" Version="0.2.0" />
<PackageVersion Include="Chronicler.Core.Lean" Version="0.2.0" />
<PackageReference Include="Chronicler.Core.Lean" />
paket add Chronicler.Core.Lean --version 0.2.0
#r "nuget: Chronicler.Core.Lean, 0.2.0"
#:package Chronicler.Core.Lean@0.2.0
#addin nuget:?package=Chronicler.Core.Lean&version=0.2.0
#tool nuget:?package=Chronicler.Core.Lean&version=0.2.0
Chronicler
![]()
Chronicler is a deterministic, transport-neutral serialization library for lockstep simulation, snapshot/restore workflows, and runtime state transfer into existing object graphs.
Unlike attribute-only serializers, Chronicler makes each type explicitly own its serialized shape through RecordData(IChronicler chronicler).
Key Features
- Deterministic record passes for systems that care about stable, explicit state flow.
- Transport-neutral core API with built-in JSON support and an optional built-in MemoryPack transport in the standard package.
- Type-owned schemas through
IRecordable, without requiring serializer attributes on most domain types. - Canonical default handling so omitted entries load into known values instead of ambient runtime state.
- Deep graph support for nested owned objects and structs already present in the runtime shell.
- Stable link support for runtime-owned or external references through a session-scoped registry.
- Designed for lockstep and restore flows where the host owns construction and Chronicler owns state transfer.
Installation
NuGet
- Choose the package that fits your runtime:
Chronicler.CoreThe standard package. Includes the full Chronicler API with built-in JSON and MemoryPack transports. Its external package surface is limited to the transport dependencies needed for those built-ins.Chronicler.Core.LeanThe lean package. Keeps the same core deterministic recording API and JSON transport, but removes theMemoryPackdependency and generated transport surface.
- Install via NuGet:
- Standard package:
dotnet add package Chronicler.Core
- Lean package:
dotnet add package Chronicler.Core.Lean
Source
git clone https://github.com/mrdav30/Chronicler.git
Then reference src/Chronicler/Chronicler.csproj directly or build the package locally.
Package Variants
Chronicler is published in two build variants so you can choose between built-in binary transport support and a smaller dependency surface:
Chronicler.CoreIncludes bothJsonRecordSerializerandMemoryPackRecordSerializer. This is the best default choice when you want the built-in MemoryPack transport.Chronicler.Core.LeanExcludes theMemoryPackpackage, compiles out the built-in MemoryPack transport files, and keeps internal shim attributes so the same codebase can build without the dependency. Choose this when you only need JSON, when you plan to supply your own binary transport, or when you want to avoidMemoryPack-generated code paths entirely.
Both variants preserve the same core IRecordable / IChronicler model and deterministic state transfer semantics. The main difference is whether the package includes the built-in MemoryPack transport.
If you build from source, the repository provides matching release configurations:
Releasebuilds the standardChronicler.Corepackage.ReleaseLeanbuilds theChronicler.Core.Leanpackage.
API Overview
Chronicler is built around three primary recording lanes:
RecordValuesfor leaf values such as primitives, enums, and small deterministic structs.RecordDeep/RecordDeepStruct/RecordNullableDeepfor owned nested recordable state.RecordLinksfor stable references to runtime-owned or external objects.
Core abstractions:
IRecordableIChroniclerIStateBacked<TState>ChronicleContextChronicleLinkRegistry
Built-in transports:
JsonRecordSerializerStateJsonConverter<TRecord, TState>/StateJsonConverterFactoryMemoryPackRecordSerializerinChronicler.Core
Important design note:
- Chronicler loads into an existing initialized runtime shell. It does not construct arbitrary object graphs from transport data alone.
Quick Start
Define a recordable type
using Chronicler;
public sealed class PlayerSnapshot : IRecordable
{
public int Health = 100;
public int Mana = 50;
public WeaponState Weapon = new();
public void RecordData(IChronicler chronicler)
{
RecordValues.Look(chronicler, ref Health, "health", 100);
RecordValues.Look(chronicler, ref Mana, "mana", 50);
RecordDeep.Look(chronicler, ref Weapon, "weapon");
}
}
public sealed class WeaponState : IRecordable
{
public int Ammo = 30;
public void RecordData(IChronicler chronicler)
{
RecordValues.Look(chronicler, ref Ammo, "ammo", 30);
}
}
Serialize and populate with JSON
PlayerSnapshot source = new();
string json = JsonRecordSerializer.Serialize(source, writeIndented: true);
PlayerSnapshot target = new()
{
Weapon = new WeaponState()
};
JsonRecordSerializer.Populate(target, json);
Serialize and populate with MemoryPack
Available in Chronicler.Core. The lean package does not include the built-in MemoryPack transport.
PlayerSnapshot source = new();
byte[] data = MemoryPackRecordSerializer.Serialize(source);
PlayerSnapshot target = new()
{
Weapon = new WeaponState()
};
MemoryPackRecordSerializer.Populate(target, data);
Serialize state-backed helper types with System.Text.Json
For helper types that own a canonical state object, implement IStateBacked<TState> and provide a public constructor that accepts the same state type. Register StateJsonConverterFactory with System.Text.Json to serialize those types as a single State payload.
using System;
using System.Text.Json;
using Chronicler;
public sealed class OrderedIds : IStateBacked<OrderedIdsState>
{
private readonly string[] _items;
public OrderedIds(OrderedIdsState state)
{
_items = state.Items;
}
public OrderedIds(params string[] items)
{
_items = items;
}
public OrderedIdsState State => new()
{
Items = _items
};
}
public sealed class OrderedIdsState
{
public string[] Items { get; set; } = Array.Empty<string>();
}
var options = new JsonSerializerOptions();
options.Converters.Add(new StateJsonConverterFactory());
Stable Links
Use RecordLinks when a field points to a runtime-owned or external object that should not be serialized inline.
public sealed class ActorState : IRecordable
{
public RuntimeEntity? Target;
public void RecordData(IChronicler chronicler)
{
RuntimeEntity? target = Target;
RecordLinks.Look(chronicler, ref target, "target");
if (chronicler.Mode == SerializationMode.Loading)
Target = target;
}
}
Resolve those links through the session context:
ChronicleContext context = new();
context.Links.RegisterInstance("player-42", runtimeEntity);
For cases where the target object is only available after the rest of the graph loads, use deferred link resolution with RecordLinks.LookDeferred(...).
Design Rules
- Pass canonical declared defaults to
RecordValues.Look(...). - Use
RecordDeepfor owned nested objects that already exist in the runtime shell. - Use
RecordDeepStructfor non-nullable nested recordable structs. - Use
RecordNullableDeepfor optional nested recordable structs. - Use
RecordLinksfor runtime-owned or external references. - Keep object construction and framework bootstrap outside the base Chronicler contract.
Development
Build the solution:
dotnet build Chronicler.slnx -c Release
Run the unit tests:
dotnet test tests/Chronicler.Tests/Chronicler.Tests.csproj -c Release --no-build
Run tests with coverage:
dotnet test tests/Chronicler.Tests/Chronicler.Tests.csproj -c Release --collect:"XPlat Code Coverage" --settings coverlet.runsettings
Compatibility
netstandard2.1net8.0- Windows, Linux, and macOS
Chronicler.Core provides JSON support through System.Text.Json and binary transport support through MemoryPack.
Chronicler.Core.Lean provides the same deterministic recording API with JSON support, but omits the built-in MemoryPack transport and dependency. Chronicler does not depend on an external collections package.
Contributing
We welcome contributions. Please see CONTRIBUTING for contribution guidance and project expectations.
Contributors
- mrdav30 - Lead Developer
- Contributions are welcome through issues and pull requests.
Community & Support
For bug reports or feature requests, please open an issue in this repository.
For general discussion and support, join the official Discord community:
License
This project is licensed under the MIT License.
See the following files for details:
LICENSE- standard MIT licenseNOTICE- additional terms regarding project branding and redistributionCOPYRIGHT- authorship information
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- System.Text.Json (>= 10.0.7)
-
net8.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Chronicler.Core.Lean:
| Package | Downloads |
|---|---|
|
SwiftCollections.Lean
SwiftCollections is a high-performance, memory-efficient library of collections designed for game development, simulations, and other performance-critical applications. |
|
|
Trailblazer.Lean
Deterministic, framework-agnostic pathfinding and navigation for lockstep simulations and games. Trailblazer combines FixedMathSharp fixed-point math, GridForge voxel navigation charts, A* paths, flow fields, reusable guide caching, transition-aware routing, steering, turning, locomotion, heightmaps, and Chronicler serialization support. |
GitHub repositories
This package is not used by any popular GitHub repositories.