using System; using System.Buffers; using System.Collections.Generic; using System.Text; namespace Cysharp.Text { internal static class EnumUtil // where T : Enum { const string InvalidName = "$"; static readonly Dictionary names; static readonly Dictionary utf8names; static EnumUtil() { var enumNames = Enum.GetNames(typeof(T)); var values = #if NET7_0_OR_GREATER Enum.GetValuesAsUnderlyingType(typeof(T)); #else Enum.GetValues(typeof(T)); #endif names = new Dictionary(enumNames.Length); utf8names = new Dictionary(enumNames.Length); for (int i = 0; i < enumNames.Length; i++) { var value = (T)values.GetValue(i)!; if (names.ContainsKey(value)) { // already registered = invalid. names[value] = InvalidName; utf8names[value] = Array.Empty(); // byte[0] == Invalid. } else { names.Add(value, enumNames[i]); utf8names.Add(value, Encoding.UTF8.GetBytes(enumNames[i])); } } } public static bool TryFormatUtf16(T value, Span dest, out int written, ReadOnlySpan _) { if (!names.TryGetValue(value, out var v) || v == InvalidName) { v = value!.ToString(); // T is Enum, not null always } written = v.Length; return v.AsSpan().TryCopyTo(dest); } public static bool TryFormatUtf8(T value, Span dest, out int written, StandardFormat _) { if (!utf8names.TryGetValue(value, out var v) || v.Length == 0) { v = Encoding.UTF8.GetBytes(value!.ToString()); } written = v.Length; return v.AsSpan().TryCopyTo(dest); } } }