https://github.com/hexaengine/hexaengine.sappho
A high-performance, source-generated binary serialization library for .NET
https://github.com/hexaengine/hexaengine.sappho
Last synced: 6 months ago
JSON representation
A high-performance, source-generated binary serialization library for .NET
- Host: GitHub
- URL: https://github.com/hexaengine/hexaengine.sappho
- Owner: HexaEngine
- License: mit
- Created: 2025-11-13T11:26:57.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-11-13T13:09:45.000Z (7 months ago)
- Last Synced: 2025-11-13T13:25:09.700Z (7 months ago)
- Language: C#
- Homepage:
- Size: 224 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE.txt
Awesome Lists containing this project
README
# HexaEngine.Sappho
A high-performance, source-generated binary serialization library for .NET with support for polymorphism, cyclic references, and efficient memory management. Part of the [HexaEngine](https://github.com/HexaEngine/HexaEngine) game engine ecosystem.
## Overview
HexaEngine.Sappho is a specialized serialization library designed for game development scenarios where performance is critical. Originally developed as a submodule for the HexaEngine game engine, it provides efficient binary serialization suitable for:
- **Game State Persistence**: Save/load game states with complex object graphs
- **Network Communication**: Fast serialization for multiplayer game data
- **Asset Management**: Efficient binary formats for game assets
- **Scene Serialization**: Handling complex game object hierarchies with circular references
While designed for game engines, Sappho is a standalone library suitable for any .NET application requiring high-performance binary serialization.
## Features
- **🚀 High Performance**: Optimized for speed with unsafe code and minimal allocations
- **🔄 Cyclic References**: Automatic handling of circular object references
- **🎭 Polymorphism**: First-class support for polymorphic serialization and deserialization
- **⚙️ Source Generation**: Uses C# source generators for compile-time serialization code generation
- **🔧 Flexible**: Support for primitives, strings, enums, structs, and complex object graphs
- **💾 Efficient**: Binary format with endian-aware operations
- **🎯 Type-Safe**: Strongly-typed serialization with compile-time validation
## Installation
```bash
dotnet add package HexaEngine.Sappho
```
## Quick Start
### 1. Mark Your Classes
Use the `[SapphoObject]` attribute to mark classes or structs for serialization:
```csharp
using HexaEngine.Sappho;
[SapphoObject]
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
public float Height { get; set; }
}
```
> **Note**: Classes must be marked as `partial` to allow the source generator to add serialization code.
### 2. Serialize and Deserialize
```csharp
// Create a serialization context
var context = new SapphoSerializationContext();
// Create an object
var person = new Person
{
Name = "John Doe",
Age = 30,
Height = 5.9f
};
// Serialize
using var writer = new SapphoWriter(context);
writer.WriteObject(person);
// Deserialize
var reader = new SapphoReader(writer.Buffer, writer.Count, context);
var deserializedPerson = reader.ReadObject();
```
## Advanced Features
### Polymorphic Serialization
Use the `[SapphoPolymorphic]` attribute to enable polymorphic serialization:
```csharp
[SapphoObject]
public partial class Animal
{
public string Name { get; set; }
}
[SapphoObject]
public partial class Dog : Animal
{
public string Breed { get; set; }
}
[SapphoObject]
public partial class Cat : Animal
{
public int LivesRemaining { get; set; }
}
[SapphoObject]
public partial class Zoo
{
[SapphoPolymorphic]
public Animal[] Animals { get; set; }
}
```
When using polymorphic types, register them with the serialization context:
```csharp
context.RegisterType(Animal.SapphoTypeId);
context.RegisterType(Dog.SapphoTypeId);
context.RegisterType(Cat.SapphoTypeId);
var zoo = new Zoo
{
Animals = new Animal[]
{
new Dog { Name = "Buddy", Breed = "Golden Retriever" },
new Cat { Name = "Whiskers", LivesRemaining = 9 }
}
};
```
### Cyclic References
The library automatically handles cyclic references:
```csharp
[SapphoObject]
public partial class Node
{
public string Name { get; set; }
public Node? Next { get; set; }
}
var node1 = new Node { Name = "Node 1" };
var node2 = new Node { Name = "Node 2" };
node1.Next = node2;
node2.Next = node1; // Cyclic reference
// Serialization will handle this correctly
```
### Ignoring Properties
Use `[SapphoIgnore]` to exclude properties from serialization:
```csharp
[SapphoObject]
public partial class CachedData
{
public string Data { get; set; }
[SapphoIgnore]
public string CachedValue { get; set; } // Not serialized
}
```
### Custom Member Attributes
Use `[SapphoMember]` for fine-grained control over serialization:
```csharp
[SapphoObject]
public partial class CustomClass
{
[SapphoMember]
public string ImportantField { get; set; }
}
```
## Supported Types
- **Primitives**: `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `float`, `double`, `bool`, `char`
- **Strings**: UTF-8 encoded with automatic null handling
- **Enums**: All enum types with any underlying integral type
- **Structs**: Value types that implement `ISapphoSerializable`
- **Classes**: Reference types with automatic reference tracking
- **Arrays**: Single-dimensional arrays of supported types
- **Nullable Types**: Full support for nullable reference and value types
## Performance
HexaEngine.Sappho is designed for high-performance scenarios:
```csharp
// From the Example project:
// Average serialization time: ~XXX ns (depends on object complexity)
```
The library uses:
- Unsafe code for direct memory access
- Stack allocations for small buffers
- Efficient buffer management with dynamic resizing
- Endian-aware binary format
## Architecture
### Core Components
- **SapphoWriter**: Handles serialization to a binary buffer
- **SapphoReader**: Handles deserialization from a binary buffer
- **SapphoSerializationContext**: Manages type registration and reference tracking
- **Source Generator**: Automatically generates serialization code at compile time
### Interfaces
- **`ISapphoSerializable`**: Base interface for serializable types
- **`ISapphoSerializer`**: Custom serializer interface
- **`ISapphoInstanceId`**: Optional interface for custom instance ID tracking
## Project Structure
```
HexaEngine.Sappho/
├── HexaEngine.Sappho/ # Core serialization library
├── HexaEngine.Sappho.Analyzer/ # Source generator
├── HexaEngine.Sappho.Tests/ # Unit tests
└── Example/ # Example usage
```
## Requirements
- **.NET 9.0** or later (core library)
- **.NET Standard 2.0** or later (analyzer)
- **C# 12** or later (for source generation features)
## Building
```bash
dotnet build
```
## Testing
```bash
dotnet test
```
The test suite includes comprehensive tests for:
- Primitive type serialization
- String handling (including Unicode and empty strings)
- Enum serialization
- Struct serialization
- Polymorphic serialization
- Cyclic reference handling
- Null value handling
## Contributing
Contributions are welcome! Please ensure:
- All tests pass
- Code follows existing conventions
- New features include appropriate tests
## License
This project is licensed under the MIT License. See the [LICENSE](https://github.com/HexaEngine/HexaEngine.Sappho/blob/main/LICENSE.txt) file for more details.
## Credits
Part of the HexaEngine ecosystem.
Developed as a submodule for [HexaEngine](https://github.com/HexaEngine/HexaEngine) - a modern game engine for .NET.
## See Also
- [HexaEngine](https://github.com/HexaEngine/HexaEngine) - The main game engine project
- [Hexa.NET.Utilities](https://github.com/HexaEngine/Hexa.NET.Utilities) - Utility library used by Sappho
---
**Do you listen to girl in red?**