167 lines
6.7 KiB
C#
167 lines
6.7 KiB
C#
using System.Runtime.CompilerServices;
|
|
using AyCode.Core.Compression;
|
|
|
|
namespace AyCode.Core.Serializers.Binaries;
|
|
|
|
/// <summary>
|
|
/// Options for AcBinarySerializer and AcBinaryDeserializer.
|
|
/// Optimized for speed and memory efficiency over raw size.
|
|
/// </summary>
|
|
public sealed class AcBinarySerializerOptions : AcSerializerOptions
|
|
{
|
|
public override AcSerializerType SerializerType { get; init; } = AcSerializerType.Binary;
|
|
|
|
/// <summary>
|
|
/// Current binary format version. Incremented when breaking changes are made.
|
|
/// </summary>
|
|
public const byte FormatVersion = 1;
|
|
|
|
/// <summary>
|
|
/// Default options instance with metadata and string interning enabled.
|
|
/// Returns a new instance each time to prevent shared state corruption.
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions Default => new();
|
|
|
|
/// <summary>
|
|
/// Options optimized for maximum speed (no interning, no references).
|
|
/// Use when deserializer knows the exact type structure.
|
|
/// Returns a new instance each time to prevent shared state corruption.
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions FastMode => new()
|
|
{
|
|
UseStringInterning = StringInterningMode.None,
|
|
ReferenceHandling = ReferenceHandlingMode.None
|
|
};
|
|
|
|
/// <summary>
|
|
/// Options for shallow serialization (root level only).
|
|
/// Returns a new instance each time to prevent shared state corruption.
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions ShallowCopy => new()
|
|
{
|
|
MaxDepth = 0,
|
|
UseStringInterning = StringInterningMode.None,
|
|
ReferenceHandling = ReferenceHandlingMode.None
|
|
};
|
|
|
|
/// <summary>
|
|
/// Options optimized for WASM environment with string caching enabled.
|
|
/// Returns a new instance each time to prevent shared state corruption.
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions WasmOptimized => new()
|
|
{
|
|
IsWasm = true,
|
|
UseStringCaching = true
|
|
};
|
|
|
|
/// <summary>
|
|
/// Whether running in WebAssembly/Browser environment.
|
|
/// When true, enables WASM-specific optimizations like string caching.
|
|
/// Default: auto-detected via OperatingSystem.IsBrowser()
|
|
/// </summary>
|
|
public bool IsWasm { get; init; } = DetectedIsWasm;
|
|
|
|
/// <summary>
|
|
/// Whether to cache short strings during deserialization to reduce allocations.
|
|
/// Most beneficial in WASM where GC is expensive.
|
|
/// Auto-enabled when IsWasm is true, can be overridden.
|
|
/// Default: follows IsWasm setting
|
|
/// </summary>
|
|
public bool UseStringCaching { get; private init; } = DetectedIsWasm;
|
|
|
|
/// <summary>
|
|
/// Maximum string length to cache when UseStringCaching is enabled.
|
|
/// Longer strings are not cached to avoid memory bloat.
|
|
/// Default: 64 characters
|
|
/// </summary>
|
|
public int MaxCachedStringLength { get; init; } = 64;
|
|
|
|
/// <summary>
|
|
/// Whether to include property hash metadata in footer for cross-type deserialization.
|
|
/// When enabled, property name hashes (FNV-1a) are written per type in the footer,
|
|
/// allowing the deserializer to match properties by name between different types.
|
|
/// Default: false (no overhead)
|
|
/// </summary>
|
|
public bool UseMetadata { get; init; } = true;
|
|
|
|
/// <summary>
|
|
/// When true, checks for duplicate property name hashes during serialization (UseMetadata mode).
|
|
/// Throws exception if FNV-1a hash collision is detected between property names of the same type.
|
|
/// Should be enabled during development/testing, can be disabled in production for performance.
|
|
/// Default: true (safety first)
|
|
/// </summary>
|
|
public bool CheckDuplicatePropName { get; init; } = true;
|
|
|
|
/// <summary>
|
|
/// Controls how string interning is applied during serialization.
|
|
/// None: No interning, all strings written inline.
|
|
/// Attribute: Only properties with [AcStringIntern(true)] are interned.
|
|
/// All: All strings within length limits are interned (legacy behavior).
|
|
/// Default: All
|
|
/// </summary>
|
|
public StringInterningMode UseStringInterning { get; set; } = StringInterningMode.All;
|
|
|
|
/// <summary>
|
|
/// Minimum string length to consider for interning.
|
|
/// Shorter strings are written inline to avoid overhead.
|
|
/// Default: 4 (strings shorter than 4 chars are not interned)
|
|
/// </summary>
|
|
public byte MinStringInternLength { get; init; } = 4;
|
|
|
|
/// <summary>
|
|
/// Maximum string length to consider for interning.
|
|
/// Longer strings (descriptions, notes, etc.) are usually unique and not worth interning.
|
|
/// Set to 0 to disable max limit.
|
|
/// Default: 64 (strings longer than 64 chars are not interned)
|
|
/// </summary>
|
|
public byte MaxStringInternLength { get; init; } = 64;
|
|
|
|
/// <summary>
|
|
/// Initial capacity for serialization buffer.
|
|
/// Default: 4096 bytes
|
|
/// </summary>
|
|
public int InitialBufferCapacity { get; init; } = 4096;
|
|
|
|
/// <summary>
|
|
/// Optional property-level filter invoked before metadata registration and serialization.
|
|
/// Return false to exclude the property from the payload.
|
|
/// </summary>
|
|
public BinaryPropertyFilter? PropertyFilter { get; init; }
|
|
|
|
/// <summary>
|
|
/// When true, PopulateMerge will remove items from destination collections
|
|
/// that have no matching Id in the source data.
|
|
/// Only applies to IId collections during merge operations.
|
|
/// Default: false (orphaned items are kept)
|
|
/// </summary>
|
|
public bool RemoveOrphanedItems { get; init; } = false;
|
|
|
|
/// <summary>
|
|
/// Controls LZ4 compression for serialized data.
|
|
/// None: No compression (default, fastest).
|
|
/// Block: Compresses entire payload as single block (better compression ratio).
|
|
/// BlockArray: Compresses in 64KB chunks (streaming-friendly, lower memory).
|
|
/// Note: Both modes are WASM-compatible (pure managed implementation).
|
|
/// Default: None
|
|
/// </summary>
|
|
public Lz4CompressionMode UseCompression { get; set; } = Lz4CompressionMode.None;
|
|
|
|
/// <summary>
|
|
/// Creates options with specified max depth.
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static AcBinarySerializerOptions WithMaxDepth(byte maxDepth) => new() { MaxDepth = maxDepth };
|
|
|
|
/// <summary>
|
|
/// Creates options without reference handling (and string interning disabled for speed).
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions WithoutReferenceHandling => new()
|
|
{
|
|
ReferenceHandling = ReferenceHandlingMode.None,
|
|
};
|
|
|
|
/// <summary>
|
|
/// Creates options without metadata (faster but less flexible).
|
|
/// </summary>
|
|
public static AcBinarySerializerOptions WithoutMetadata => new() { UseMetadata = false };
|
|
} |