#nullable enable using System; using System.Text; using System.Buffers; using System.IO; using Newtonsoft.Json; namespace ShrinkNetwork { public sealed class ShrinkJsonNetworkSerializer : IShrinkNetworkBufferSerializer { private static readonly JsonSerializerSettings Settings = new() { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Include, Formatting = Formatting.None }; public byte[] Serialize(object value) => Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value, Settings)); public object Deserialize(byte[] payload, Type type) => JsonConvert.DeserializeObject(Encoding.UTF8.GetString(payload), type, Settings) ?? throw new JsonSerializationException($"Failed to deserialize payload into {type.FullName}."); public T Deserialize(byte[] payload) => JsonConvert.DeserializeObject(Encoding.UTF8.GetString(payload), Settings) ?? throw new JsonSerializationException($"Failed to deserialize payload into {typeof(T).FullName}."); public void Serialize(IBufferWriter writer, object value) { using var stream = new BufferStream(writer); using var text = new StreamWriter(stream, new UTF8Encoding(false), 1024, leaveOpen: true); using var json = new JsonTextWriter(text); JsonSerializer.Create(Settings).Serialize(json, value); } public object Deserialize(ReadOnlyMemory payload, Type type) => JsonConvert.DeserializeObject(Encoding.UTF8.GetString(payload.Span), type, Settings) ?? throw new JsonSerializationException($"Failed to deserialize payload into {type.FullName}."); private sealed class BufferStream : Stream { private readonly IBufferWriter _writer; public BufferStream(IBufferWriter writer) => _writer = writer; public override bool CanRead => false; public override bool CanSeek => false; public override bool CanWrite => true; public override long Length => throw new NotSupportedException(); public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } public override void Flush() { } public override void Write(byte[] buffer, int offset, int count) { buffer.AsSpan(offset, count).CopyTo(_writer.GetSpan(count)); _writer.Advance(count); } public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException(); public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); public override void SetLength(long value) => throw new NotSupportedException(); } } }