mirror of
https://github.com/StarBeat/UnityDependencyAnalyzer.git
synced 2026-03-08 05:35:27 +08:00
213 lines
6.8 KiB
C#
213 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
#nullable enable
|
|
using MemoryPack.Internal;
|
|
using System.Buffers;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace MemoryPack {
|
|
|
|
#if NET7_0_OR_GREATER
|
|
using static MemoryMarshal;
|
|
using static GC;
|
|
#else
|
|
using static MemoryPack.Internal.MemoryMarshalEx;
|
|
#endif
|
|
|
|
public static partial class MemoryPackSerializer
|
|
{
|
|
[ThreadStatic]
|
|
static SerializerWriterThreadStaticState? threadStaticState;
|
|
[ThreadStatic]
|
|
static MemoryPackWriterOptionalState? threadStaticWriterOptionalState;
|
|
|
|
public static byte[] Serialize<T>(in T? value, MemoryPackSerializerOptions? options = default)
|
|
{
|
|
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
|
{
|
|
var array = AllocateUninitializedArray<byte>(Unsafe.SizeOf<T>());
|
|
Unsafe.WriteUnaligned(ref GetArrayDataReference(array), value);
|
|
return array;
|
|
}
|
|
#if NET7_0_OR_GREATER
|
|
var typeKind = TypeHelpers.TryGetUnmanagedSZArrayElementSizeOrMemoryPackableFixedSize<T>(out var elementSize);
|
|
if (typeKind == TypeHelpers.TypeKind.None)
|
|
{
|
|
// do nothing
|
|
}
|
|
else if (typeKind == TypeHelpers.TypeKind.UnmanagedSZArray)
|
|
{
|
|
if (value == null)
|
|
{
|
|
return MemoryPackCode.NullCollectionData.ToArray();
|
|
}
|
|
|
|
var srcArray = ((Array)(object)value!);
|
|
var length = srcArray.Length;
|
|
if (length == 0)
|
|
{
|
|
return new byte[4] { 0, 0, 0, 0 };
|
|
}
|
|
|
|
var dataSize = elementSize * length;
|
|
var destArray = AllocateUninitializedArray<byte>(dataSize + 4);
|
|
ref var head = ref MemoryMarshal.GetArrayDataReference(destArray);
|
|
|
|
Unsafe.WriteUnaligned(ref head, length);
|
|
Unsafe.CopyBlockUnaligned(ref Unsafe.Add(ref head, 4), ref MemoryMarshal.GetArrayDataReference(srcArray), (uint)dataSize);
|
|
|
|
return destArray;
|
|
}
|
|
else if (typeKind == TypeHelpers.TypeKind.FixedSizeMemoryPackable)
|
|
{
|
|
var buffer = new byte[(value == null) ? 1 : elementSize];
|
|
var bufferWriter = new FixedArrayBufferWriter(buffer);
|
|
var writer = new MemoryPackWriter<FixedArrayBufferWriter>(ref bufferWriter, buffer, MemoryPackWriterOptionalState.NullState);
|
|
Serialize(ref writer, value);
|
|
return bufferWriter.GetFilledBuffer();
|
|
}
|
|
#endif
|
|
|
|
var state = threadStaticState;
|
|
if (state == null)
|
|
{
|
|
state = threadStaticState = new SerializerWriterThreadStaticState();
|
|
}
|
|
state.Init(options);
|
|
|
|
try
|
|
{
|
|
var writer = new MemoryPackWriter(ref Unsafe.As<ReusableLinkedArrayBufferWriter, IBufferWriter<byte>>(ref state.BufferWriter), state.BufferWriter.DangerousGetFirstBuffer(), state.OptionalState);
|
|
Serialize(ref writer, value);
|
|
return state.BufferWriter.ToArrayAndReset();
|
|
}
|
|
finally
|
|
{
|
|
state.Reset();
|
|
}
|
|
}
|
|
|
|
public static unsafe void Serialize<T>(in IBufferWriter<byte> bufferWriter, in T? value, MemoryPackSerializerOptions? options = default)
|
|
#if NET7_0_OR_GREATER
|
|
|
|
#else
|
|
|
|
#endif
|
|
{
|
|
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
|
{
|
|
var buffer = bufferWriter.GetSpan(Unsafe.SizeOf<T>());
|
|
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(buffer), value);
|
|
bufferWriter.Advance(Unsafe.SizeOf<T>());
|
|
return;
|
|
}
|
|
#if NET7_0_OR_GREATER
|
|
var typeKind = TypeHelpers.TryGetUnmanagedSZArrayElementSizeOrMemoryPackableFixedSize<T>(out var elementSize);
|
|
if (typeKind == TypeHelpers.TypeKind.UnmanagedSZArray)
|
|
{
|
|
if (value == null)
|
|
{
|
|
var span = bufferWriter.GetSpan(4);
|
|
MemoryPackCode.NullCollectionData.CopyTo(span);
|
|
bufferWriter.Advance(4);
|
|
return;
|
|
}
|
|
|
|
var srcArray = ((Array)(object)value!);
|
|
var length = srcArray.Length;
|
|
if (length == 0)
|
|
{
|
|
var span = bufferWriter.GetSpan(4);
|
|
MemoryPackCode.ZeroCollectionData.CopyTo(span);
|
|
bufferWriter.Advance(4);
|
|
return;
|
|
}
|
|
var dataSize = elementSize * length;
|
|
var destSpan = bufferWriter.GetSpan(dataSize + 4);
|
|
ref var head = ref MemoryMarshal.GetReference(destSpan);
|
|
|
|
Unsafe.WriteUnaligned(ref head, length);
|
|
Unsafe.CopyBlockUnaligned(ref Unsafe.Add(ref head, 4), ref MemoryMarshal.GetArrayDataReference(srcArray), (uint)dataSize);
|
|
|
|
bufferWriter.Advance(dataSize + 4);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
var state = threadStaticWriterOptionalState;
|
|
if (state == null)
|
|
{
|
|
state = threadStaticWriterOptionalState = new MemoryPackWriterOptionalState();
|
|
}
|
|
state.Init(options);
|
|
|
|
try
|
|
{
|
|
var writer = new MemoryPackWriter(ref Unsafe.AsRef(bufferWriter), state);
|
|
Serialize(ref writer, value);
|
|
}
|
|
finally
|
|
{
|
|
state.Reset();
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static void Serialize<T>(ref MemoryPackWriter writer, in T? value)
|
|
#if NET7_0_OR_GREATER
|
|
|
|
#else
|
|
|
|
#endif
|
|
{
|
|
writer.WriteValue(value);
|
|
writer.Flush();
|
|
}
|
|
|
|
public static async ValueTask SerializeAsync<T>(Stream stream, T? value, MemoryPackSerializerOptions? options = default, CancellationToken cancellationToken = default)
|
|
{
|
|
var tempWriter = ReusableLinkedArrayBufferWriterPool.Rent();
|
|
try
|
|
{
|
|
Serialize(tempWriter, value, options);
|
|
await tempWriter.WriteToAndResetAsync(stream, cancellationToken).ConfigureAwait(false);
|
|
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
ReusableLinkedArrayBufferWriterPool.Return(tempWriter);
|
|
}
|
|
}
|
|
|
|
sealed class SerializerWriterThreadStaticState
|
|
{
|
|
public ReusableLinkedArrayBufferWriter BufferWriter;
|
|
public MemoryPackWriterOptionalState OptionalState;
|
|
|
|
public SerializerWriterThreadStaticState()
|
|
{
|
|
BufferWriter = new ReusableLinkedArrayBufferWriter(useFirstBuffer: true, pinned: true);
|
|
OptionalState = new MemoryPackWriterOptionalState();
|
|
}
|
|
|
|
public void Init(MemoryPackSerializerOptions? options)
|
|
{
|
|
OptionalState.Init(options);
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
BufferWriter.Reset();
|
|
OptionalState.Reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
} |