Files
Studio/Assets/Scripts/ExternalAssets/MessagePack/Formatters/StringInterningFormatter.cs
2025-05-21 12:10:38 +09:00

62 lines
2.1 KiB
C#

// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.NET.StringTools;
#nullable enable
namespace MessagePack.Formatters
{
/// <summary>
/// A <see cref="string" /> formatter that interns strings on deserialization.
/// </summary>
public sealed class StringInterningFormatter : IMessagePackFormatter<string?>
{
/// <inheritdoc/>
public string? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
MessagePackReader retryReader = reader;
if (reader.TryReadStringSpan(out ReadOnlySpan<byte> bytes))
{
if (bytes.Length < 4096)
{
if (bytes.Length == 0)
{
return string.Empty;
}
Span<char> chars = stackalloc char[bytes.Length];
int charLength;
#if SPAN_BUILTIN || UNITY_2021_2_OR_NEWER
charLength = StringEncoding.UTF8.GetChars(bytes, chars);
#else
unsafe
{
fixed (byte* pBytes = bytes)
fixed (char* pChars = chars)
{
charLength = StringEncoding.UTF8.GetChars(pBytes, bytes.Length, pChars, chars.Length);
}
}
#endif
return Strings.WeakIntern(chars.Slice(0, charLength));
}
else
{
// Rewind the reader to the start of the string because we're taking the slow path.
reader = retryReader;
}
}
return reader.ReadString() is string s ? Strings.WeakIntern(s) : null;
}
/// <inheritdoc/>
public void Serialize(ref MessagePackWriter writer, string? value, MessagePackSerializerOptions options) => writer.Write(value);
}
}