Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement ISpanFormattable on Enum
  • Loading branch information
stephentoub committed Dec 2, 2022
commit 90cf715642ff40a80dca665578f8b457d21d2256
70 changes: 66 additions & 4 deletions src/libraries/System.Private.CoreLib/src/System/Enum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace System
/// <summary>Provides the base class for enumerations.</summary>
[Serializable]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract partial class Enum : ValueType, IComparable, IFormattable, IConvertible
public abstract partial class Enum : ValueType, IComparable, ISpanFormattable, IConvertible
{
/// <summary>Character used to separate flag enum values when formatted in a list.</summary>
private const char EnumSeparatorChar = ',';
Expand Down Expand Up @@ -1759,6 +1759,62 @@ public static string Format(Type enumType, object value, [StringSyntax(StringSyn
throw CreateInvalidFormatSpecifierException();
}

/// <summary>Tries to format the value of the enum into the provided span of characters.</summary>
/// <param name="destination">The span in which to write this instance's value formatted as a span of characters.</param>
/// <param name="charsWritten">When this method returns, contains the number of characters that were written in destination.</param>
/// <param name="format">The format specifier.</param>
/// <param name="provider">An optional object that supplies culture-specific formatting information for destination. This is ignored.</param>
/// <returns><see langword="true"/> if the formatting was successful; otherwise, <see langword="false"/>.</returns>
bool ISpanFormattable.TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
{
RuntimeType enumType = (RuntimeType)GetType();
ref byte rawData = ref this.GetRawData();
CorElementType corElementType = InternalGetCorElementType();

if (format.IsEmpty)
{
return corElementType switch
{
CorElementType.ELEMENT_TYPE_I1 => TryFormatPrimitiveDefault(enumType, (sbyte)rawData, destination, out charsWritten),
CorElementType.ELEMENT_TYPE_U1 => TryFormatPrimitiveDefault(enumType, rawData, destination, out charsWritten),
CorElementType.ELEMENT_TYPE_I2 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, short>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_U2 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, ushort>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_I4 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, int>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_U4 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, uint>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_I8 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, long>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_U8 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, ulong>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_CHAR => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, char>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_R4 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, float>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_R8 => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, double>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_I => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, nint>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_U => TryFormatPrimitiveDefault(enumType, Unsafe.As<byte, nuint>(ref rawData), destination, out charsWritten),
CorElementType.ELEMENT_TYPE_BOOLEAN => TryFormatBool(enumType, rawData != 0, destination, out charsWritten, format),
_ => throw CreateUnknownEnumTypeException(),
};
}
else
{
return corElementType switch
{
CorElementType.ELEMENT_TYPE_I1 => TryFormatPrimitiveNonDefault(enumType, (sbyte)rawData, destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_U1 => TryFormatPrimitiveNonDefault(enumType, rawData, destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_I2 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, short>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_U2 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, ushort>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_I4 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, int>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_U4 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, uint>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_I8 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, long>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_U8 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, ulong>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_CHAR => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, char>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_R4 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, float>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_R8 => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, double>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_I => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, nint>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_U => TryFormatPrimitiveNonDefault(enumType, Unsafe.As<byte, nuint>(ref rawData), destination, out charsWritten, format),
CorElementType.ELEMENT_TYPE_BOOLEAN => TryFormatBool(enumType, rawData != 0, destination, out charsWritten, format),
_ => throw CreateUnknownEnumTypeException(),
};
}
}

/// <summary>Tries to format the value of the enumerated type instance into the provided span of characters.</summary>
/// <typeparam name="TEnum"></typeparam>
/// <param name="value"></param>
Expand Down Expand Up @@ -1913,9 +1969,15 @@ private static bool TryFormatPrimitiveNonDefault<TUnderlyingValue>(RuntimeType e
{
switch (format[0] | 0x20)
{
case 'g': return TryFormatPrimitiveDefault(enumType, value, destination, out charsWritten);
case 'd': return value.TryFormat(destination, out charsWritten, format: default, provider: null);
case 'x': return TryFormatNumberAsHex<TUnderlyingValue>(ref Unsafe.As<TUnderlyingValue, byte>(ref value), destination, out charsWritten);
case 'g':
return TryFormatPrimitiveDefault(enumType, value, destination, out charsWritten);

case 'd':
return value.TryFormat(destination, out charsWritten, format: default, provider: null);

case 'x':
return TryFormatNumberAsHex<TUnderlyingValue>(ref Unsafe.As<TUnderlyingValue, byte>(ref value), destination, out charsWritten);

case 'f':
bool destinationIsTooSmall = false;
if (TryFormatFlagNames(GetEnumInfo<TUnderlyingValue>(enumType), value, destination, out charsWritten, ref destinationIsTooSmall) ||
Expand Down
3 changes: 2 additions & 1 deletion src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2311,7 +2311,7 @@ protected EntryPointNotFoundException(System.Runtime.Serialization.Serialization
public EntryPointNotFoundException(string? message) { }
public EntryPointNotFoundException(string? message, System.Exception? inner) { }
}
public abstract partial class Enum : System.ValueType, System.IComparable, System.IConvertible, System.IFormattable
public abstract partial class Enum : System.ValueType, System.IComparable, System.IConvertible, System.ISpanFormattable
{
protected Enum() { }
public int CompareTo(object? target) { throw null; }
Expand Down Expand Up @@ -2375,6 +2375,7 @@ protected Enum() { }
[System.ObsoleteAttribute("The provider argument is not used. Use ToString(String) instead.")]
public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("EnumFormat")] string? format, System.IFormatProvider? provider) { throw null; }
public static bool TryFormat<TEnum>(TEnum value, System.Span<char> destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("EnumFormat")] System.ReadOnlySpan<char> format = default(System.ReadOnlySpan<char>)) where TEnum : struct { throw null; }
bool ISpanFormattable.TryFormat(System.Span<char> destination, out int charsWritten, System.ReadOnlySpan<char> format, System.IFormatProvider? provider) { throw null; }
public static bool TryParse(System.Type enumType, System.ReadOnlySpan<char> value, bool ignoreCase, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out object? result) { throw null; }
public static bool TryParse(System.Type enumType, System.ReadOnlySpan<char> value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out object? result) { throw null; }
public static bool TryParse(System.Type enumType, string? value, bool ignoreCase, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out object? result) { throw null; }
Expand Down