#nullable enable using System; using System.Buffers; using MessagePack; using MessagePack.Formatters; namespace ShrinkNetwork.MessagePack { /// Pass a generated-only resolver; register all message types before starting transports. public sealed class ShrinkMessagePackNetworkSerializer : ShrinkRegisteredNetworkSerializer { private readonly MessagePackSerializerOptions _options; public ShrinkMessagePackNetworkSerializer(IFormatterResolver generatedResolver) { _options = MessagePackSerializerOptions.Standard .WithResolver(global::MessagePack.Resolvers.CompositeResolver.Create( generatedResolver ?? throw new ArgumentNullException(nameof(generatedResolver)), global::MessagePack.Resolvers.BuiltinResolver.Instance)) .WithSecurity(MessagePackSecurity.UntrustedData); } public void Register() => Register(new FormatterCodec(_options)); private sealed class FormatterCodec : IShrinkMessageCodec { private readonly IMessagePackFormatter _formatter; private readonly MessagePackSerializerOptions _options; public FormatterCodec(MessagePackSerializerOptions options) { _options = options; _formatter = options.Resolver.GetFormatter() ?? throw new InvalidOperationException($"No generated MessagePack formatter for {typeof(T).FullName}."); } public void Write(IBufferWriter buffer, T value) { var writer = new MessagePackWriter(buffer); _formatter.Serialize(ref writer, value, _options); writer.Flush(); } public T Read(ReadOnlyMemory payload) { var reader = new MessagePackReader(payload); var result = _formatter.Deserialize(ref reader, _options); if (!reader.End) throw new System.IO.InvalidDataException("Trailing MessagePack payload."); return result; } } } }