#nullable enable using System; using System.Buffers; using System.Collections.Generic; namespace ShrinkNetwork { public interface IShrinkMessageCodec { void Write(IBufferWriter writer, T value); T Read(ReadOnlyMemory payload); } /// Explicit codecs work with AOT and external modules without runtime generic reflection. public class ShrinkRegisteredNetworkSerializer : IShrinkNetworkBufferSerializer { private interface ICodec { void Write(IBufferWriter writer, object value); object Read(ReadOnlyMemory payload); } private sealed class Codec : ICodec { private readonly IShrinkMessageCodec _codec; public Codec(IShrinkMessageCodec codec) => _codec = codec; public void Write(IBufferWriter writer, object value) => _codec.Write(writer, (T)value); public object Read(ReadOnlyMemory payload) => _codec.Read(payload)!; } private readonly Dictionary _codecs = new(); public void Register(IShrinkMessageCodec codec) { if (codec == null) throw new ArgumentNullException(nameof(codec)); _codecs.Add(typeof(T), new Codec(codec)); } public bool Unregister() => _codecs.Remove(typeof(T)); private ICodec Resolve(Type type) => _codecs.TryGetValue(type, out var codec) ? codec : throw new InvalidOperationException($"SHRINK-NET-CODEC: No codec registered for {type.FullName}. Register a generated formatter before binding the transport."); public void Serialize(IBufferWriter writer, object value) => Resolve(value.GetType()).Write(writer, value); public object Deserialize(ReadOnlyMemory payload, Type type) => Resolve(type).Read(payload); public byte[] Serialize(object value) { using var writer = new ShrinkBufferWriter(); Serialize(writer, value); return writer.WrittenMemory.ToArray(); } public object Deserialize(byte[] payload, Type type) => Deserialize((ReadOnlyMemory)payload, type); public T Deserialize(byte[] payload) => (T)Deserialize(payload, typeof(T)); } }