// 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 { /// /// A formatter that interns strings on deserialization. /// public sealed class StringInterningFormatter : IMessagePackFormatter { /// public string? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (reader.TryReadNil()) { return null; } MessagePackReader retryReader = reader; if (reader.TryReadStringSpan(out ReadOnlySpan bytes)) { if (bytes.Length < 4096) { if (bytes.Length == 0) { return string.Empty; } Span 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; } /// public void Serialize(ref MessagePackWriter writer, string? value, MessagePackSerializerOptions options) => writer.Write(value); } }