AyCode.Core/AyCode.Core/Serializers/Binaries/AcBinarySerializerOptions.cs

153 lines
5.9 KiB
C#

using System.Runtime.CompilerServices;
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
{
/// <summary>
/// Cached platform detection - true if running in WebAssembly/Browser environment.
/// </summary>
private static readonly bool DetectedIsWasm = OperatingSystem.IsBrowser();
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 metadata header with property names.
/// NOTE: Currently unused - deserializer uses ordered property indices, not names.
/// Kept for potential future schema evolution support.
/// Default: false (no overhead)
/// </summary>
public bool UseMetadata { get; init; } = false;
/// <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>
/// 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 };
}