AyCode.Core/AyCode.Core/Serializers/Jsons/AcJsonSerializer.JsonSerial...

105 lines
3.3 KiB
C#

using System.Buffers;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
namespace AyCode.Core.Serializers.Jsons;
public static partial class AcJsonSerializer
{
private static class SerializationContextPool
{
private static readonly ConcurrentQueue<JsonSerializationContext> Pool = new();
private const int MaxPoolSize = 16;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static JsonSerializationContext Get(in AcJsonSerializerOptions options)
{
if (Pool.TryDequeue(out var context))
{
context.Reset(options);
return context;
}
return new JsonSerializationContext(options);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Return(JsonSerializationContext context)
{
if (Pool.Count < MaxPoolSize)
{
context.Clear();
Pool.Enqueue(context);
}
}
}
private sealed class JsonSerializationContext : AcSerializeBase, IDisposable
{
private readonly ArrayBufferWriter<byte> _buffer;
public Utf8JsonWriter Writer { get; private set; }
// Use shared reference tracker from AcSerializerCommon
private readonly AcSerializerCommon.SerializationReferenceTracker _refTracker = new();
public bool UseReferenceHandling { get; private set; }
public byte MaxDepth { get; private set; }
private static readonly JsonWriterOptions WriterOptions = new()
{
Indented = false,
SkipValidation = true // Skip validation for performance
};
public JsonSerializationContext(in AcJsonSerializerOptions options)
{
_buffer = new ArrayBufferWriter<byte>(4096);
Writer = new Utf8JsonWriter(_buffer, WriterOptions);
Reset(options);
}
public void Reset(in AcJsonSerializerOptions options)
{
UseReferenceHandling = options.UseReferenceHandling;
MaxDepth = options.MaxDepth;
_refTracker.Reset();
if (UseReferenceHandling)
{
_refTracker.EnsureInitialized();
}
}
public void Clear()
{
Writer.Reset();
_buffer.Clear();
_refTracker.Reset();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TrackForScanning(object obj) => _refTracker.TrackForScanning(obj);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ShouldWriteId(object obj, out int id) => _refTracker.ShouldWriteId(obj, out id);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MarkAsWritten(object obj, int id) => _refTracker.MarkAsWritten(obj, id);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetExistingRef(object obj, out int refId) => _refTracker.TryGetExistingRef(obj, out refId);
public string GetResult()
{
Writer.Flush();
return Encoding.UTF8.GetString(_buffer.WrittenSpan);
}
public void Dispose()
{
Writer.Dispose();
}
}
}