Files
ShrinkNetwork/Runtime/Serialization/ShrinkRegisteredNetworkSerializer.cs
T

50 lines
2.3 KiB
C#

#nullable enable
using System;
using System.Buffers;
using System.Collections.Generic;
namespace ShrinkNetwork
{
public interface IShrinkMessageCodec<T>
{
void Write(IBufferWriter<byte> writer, T value);
T Read(ReadOnlyMemory<byte> payload);
}
/// <summary>Explicit codecs work with AOT and external modules without runtime generic reflection.</summary>
public class ShrinkRegisteredNetworkSerializer : IShrinkNetworkBufferSerializer
{
private interface ICodec
{
void Write(IBufferWriter<byte> writer, object value);
object Read(ReadOnlyMemory<byte> payload);
}
private sealed class Codec<T> : ICodec
{
private readonly IShrinkMessageCodec<T> _codec;
public Codec(IShrinkMessageCodec<T> codec) => _codec = codec;
public void Write(IBufferWriter<byte> writer, object value) => _codec.Write(writer, (T)value);
public object Read(ReadOnlyMemory<byte> payload) => _codec.Read(payload)!;
}
private readonly Dictionary<Type, ICodec> _codecs = new();
public void Register<T>(IShrinkMessageCodec<T> codec)
{
if (codec == null) throw new ArgumentNullException(nameof(codec));
_codecs.Add(typeof(T), new Codec<T>(codec));
}
public bool Unregister<T>() => _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<byte> writer, object value) => Resolve(value.GetType()).Write(writer, value);
public object Deserialize(ReadOnlyMemory<byte> 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<byte>)payload, type);
public T Deserialize<T>(byte[] payload) => (T)Deserialize(payload, typeof(T));
}
}