using System; using System.Reflection; namespace AyCode.Core.Serializers; public abstract class AcSerializerOptions { public int MaxContextPoolSize { get; init; } = 8; public abstract AcSerializerType SerializerType { get; init; } /// /// Reference handling mode for circular/shared references. /// Default: OnlyId (JSON serializer requires All mode, OnlyId not yet implemented) /// Note: Binary serializer supports OnlyId mode for IId-only tracking. /// public ReferenceHandlingMode ReferenceHandling { get => _referenceHandling; set => _referenceHandling = value; } private ReferenceHandlingMode _referenceHandling = ReferenceHandlingMode.OnlyId; private readonly byte _maxDepth = byte.MaxValue; private readonly bool _throwOnCircularReference = true; private readonly PropertyMapperDelegate? _propertyMapper; private bool _useAsync = false; public bool UseAsync { get => _useAsync && (ReferenceHandling != ReferenceHandlingMode.None); //|| UseStringIntern) init => _useAsync = !DetectedIsWasm && value; } /// /// Cached platform detection - true if running in WebAssembly/Browser environment. /// protected static readonly bool DetectedIsWasm = OperatingSystem.IsBrowser(); /// /// Maximum depth for serialization/deserialization. /// 0 = root level only (primitives of root object) /// 1 = root + first level of nested objects/collections /// byte.MaxValue (255) = effectively unlimited /// Default: byte.MaxValue /// public byte MaxDepth { get => _maxDepth; init => _maxDepth = value; } /// /// Throw exception on circular reference detection for non-IId types. /// When true: Tracks all objects and throws InvalidOperationException on circular references. /// When false: No tracking for non-IId types (faster, but circular refs may cause MaxDepth truncation). /// Default: true (production safety) /// Note: IId types are always tracked when ReferenceHandling != None. /// public bool ThrowOnCircularReference { get => _throwOnCircularReference; init => _throwOnCircularReference = value; } /// /// Optional callback for custom property mapping during cross-type operations. /// Used when deserializing/populating with Deserialize<TSource, TDest> or Populate<TSource, TDest>. /// /// Use cases: /// - Mapping between external DTOs and internal models (different class hierarchies) /// - Handling property renames across versions /// - Custom property pairing logic /// /// If null (default), properties are matched by name. /// Callback is invoked once during mapping build phase and result is cached. /// /// Performance: ZERO overhead on same-type operations (Deserialize<T>). /// public PropertyMapperDelegate? PropertyMapper { get => _propertyMapper; init => _propertyMapper = value; } } public enum AcSerializerType : byte { Json = 0, Binary = 1, Toon = 2, } /// /// Reference handling mode for serialization. /// public enum ReferenceHandlingMode : byte { /// /// No reference handling - all objects serialized inline. /// None = 0, /// /// Reference handling only for IId objects - uses semantic Id for deduplication. /// NOTE: Not fully implemented for JSON serializer - use All instead. /// Binary serializer supports this mode. /// OnlyId = 1, /// /// Full reference handling for all objects. /// All = 2 } /// /// Wire encoding mode for binary serialization. /// public enum WireMode : byte { /// /// Compact encoding: VarInt for integers, UTF-8 for strings. Smaller output. /// Compact = 0, /// /// Fast encoding: fixed-width integers, UTF-16 for strings. Larger output, faster encode/decode. /// Fast = 1 } /// /// Delegate for custom property mapping during cross-type deserialization/population. /// Enables mapping between different class hierarchies or renamed properties. /// /// Property from the source type being deserialized /// Target type being populated /// Mapped destination property, or null to skip this property public delegate PropertyInfo? PropertyMapperDelegate(PropertyInfo sourceProperty, Type destinationType);