cyriaca / Azura

source generation based serialization

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Azura

source generation based serialization

Package Release
Azura NuGet
Azura.Generator NuGet

Why?

Generating source code instead of relying on reflection is nice. For example, when using NativeAOT you should be able to strip reflection metadata and still have serialization work, as everything is hooked up at design time.

Target use case is communication between game clients and third-party programs.

  • Generates serialization constructs for structs/classes/records
    • Get-only properties / readonly fields are supported if type has partial
  • Has default serializers for common BCL types
    • byte / sbyte / ushort / short / uint / int / ulong / long
      • Also supports enum types
    • float / double / char / bool
    • Guid / TimeSpan / DateTime / decimal
    • string
    • T[] / List<T> / HashSet<T> / Dictionary<TKey, TValue>
      • Includes faster path for arrays of primitives
  • Supports nullable types (value types, reference types in nullable context)
  • Native endianness conversion (stored as little-endian)

Usage

  1. Add generator library (includes base package, does not need to be explicitly included)
<PackageReference Include="Azura.Generator" Version="version" />
  1. Define a data type and mark properties or fields
using Azura;
[Azura]
public record Data
{
    [Azura] public int Property1 { get; init; }
    [Azura] public string? Property2 { get; init; }
    [Azura] public string?[]? Property3 { get; init; }
}
  1. Serialize the data
var data = new Data {Property2 = "Execute order", Property1 = 66};
data.Serialize(stream);
  1. Retrieve the data
    • Helper types are generated as <ClassName>Serialization
var data = DataSerialization.Deserialize(stream);

Limitations

  • Cannot serialize generic types

Pending features

  • Serialize nested classes

Binary format

  • Numeric types are little-endian.
  • Primitives are serialized as expected.
  • Nullable types are prefixed with a byte flag.
  • Collections and strings are prefixed with an s32 count followed by elements serialized contiguously (if a supported type parameter is nullable, those values are prefixed with a byte flag).

Custom serialization

Custom serialization for existing library types can be added but requires manual implementation of the below signatures in a class under the target type's namespace named <ClassName>Serialization.

Value types

public static T Deserialize(Stream stream);
public static void Deserialize(Stream stream, out T self) => self = Deserialize(stream);
public static void Serialize(T self, Stream stream) => Serialize(in self, stream);
public static void Serialize(this in T self, Stream stream);

Reference types

public static T Deserialize(Stream stream);
public static void Deserialize(Stream stream, out T self) => self = Deserialize(stream);
public static void Serialize(this T self, Stream stream) => Serialize(in self, stream);
public static void Serialize(in T self, Stream stream);

About

source generation based serialization


Languages

Language:C# 100.0%