// 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 System.Buffers; using System.ComponentModel; namespace MessagePack.Internal { /// /// Helpers for generated code. /// /// /// This code is used by dynamically generated code as well as AOT generated code, /// and thus must be public for the "C# generated and compiled into saved assembly" scenario. /// [EditorBrowsable(EditorBrowsableState.Never)] public static class CodeGenHelpers { /// /// Gets the messagepack encoding for a given string. /// /// The string to encode. /// The messagepack encoding for , including messagepack header and UTF-8 bytes. public static byte[] GetEncodedStringBytes(string value) { var byteCount = StringEncoding.UTF8.GetByteCount(value); if (byteCount <= MessagePackRange.MaxFixStringLength) { var bytes = new byte[byteCount + 1]; bytes[0] = (byte)(MessagePackCode.MinFixStr | byteCount); StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 1); return bytes; } else if (byteCount <= byte.MaxValue) { var bytes = new byte[byteCount + 2]; bytes[0] = MessagePackCode.Str8; bytes[1] = unchecked((byte)byteCount); StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 2); return bytes; } else if (byteCount <= ushort.MaxValue) { var bytes = new byte[byteCount + 3]; bytes[0] = MessagePackCode.Str16; bytes[1] = unchecked((byte)(byteCount >> 8)); bytes[2] = unchecked((byte)byteCount); StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 3); return bytes; } else { var bytes = new byte[byteCount + 5]; bytes[0] = MessagePackCode.Str32; bytes[1] = unchecked((byte)(byteCount >> 24)); bytes[2] = unchecked((byte)(byteCount >> 16)); bytes[3] = unchecked((byte)(byteCount >> 8)); bytes[4] = unchecked((byte)byteCount); StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 5); return bytes; } } /// /// Gets a single containing all bytes in a given . /// An array may be allocated if the bytes are not already contiguous in memory. /// /// The sequence to get a span for. /// The span. public static ReadOnlySpan GetSpanFromSequence(in ReadOnlySequence sequence) { if (sequence.IsSingleSegment) { return sequence.First.Span; } return sequence.ToArray(); } /// /// Reads a string as a contiguous span of UTF-8 encoded characters. /// An array may be allocated if the string is not already contiguous in memory. /// /// The reader to use. /// The span of UTF-8 encoded characters. public static ReadOnlySpan ReadStringSpan(ref MessagePackReader reader) { if (!reader.TryReadStringSpan(out ReadOnlySpan result)) { return GetSpanFromSequence(reader.ReadStringSequence()); } return result; } /// /// Creates a array for a given sequence, or if the optional sequence is itself . /// /// The sequence. /// The byte array or . public static byte[] GetArrayFromNullableSequence(in ReadOnlySequence? sequence) => sequence?.ToArray(); private static ReadOnlySpan GetSpanFromSequence(in ReadOnlySequence? sequence) { return sequence.HasValue ? GetSpanFromSequence(sequence.Value) : default; } } }