|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
namespace System.Runtime.Serialization.Formatters.Binary
{
internal static class Converter
{
internal static readonly Type s_typeofISerializable = typeof(ISerializable);
internal static readonly Type s_typeofString = typeof(string);
internal static readonly Type s_typeofConverter = typeof(Converter);
internal static readonly Type s_typeofBoolean = typeof(bool);
internal static readonly Type s_typeofByte = typeof(byte);
internal static readonly Type s_typeofChar = typeof(char);
internal static readonly Type s_typeofDecimal = typeof(decimal);
internal static readonly Type s_typeofDouble = typeof(double);
internal static readonly Type s_typeofInt16 = typeof(short);
internal static readonly Type s_typeofInt32 = typeof(int);
internal static readonly Type s_typeofInt64 = typeof(long);
internal static readonly Type s_typeofSByte = typeof(sbyte);
internal static readonly Type s_typeofSingle = typeof(float);
internal static readonly Type s_typeofTimeSpan = typeof(TimeSpan);
internal static readonly Type s_typeofDateTime = typeof(DateTime);
internal static readonly Type s_typeofUInt16 = typeof(ushort);
internal static readonly Type s_typeofUInt32 = typeof(uint);
internal static readonly Type s_typeofUInt64 = typeof(ulong);
internal static readonly Type s_typeofObject = typeof(object);
internal static readonly Type s_typeofSystemVoid = typeof(void);
// In .NET Framework the default assembly is mscorlib.dll --> typeof(string).Assembly.
// In Core type string lives in System.Private.Corelib.dll which doesn't
// contain all the types which are living in mscorlib in .NET Framework. Therefore we
// use our mscorlib facade which also contains manual type forwards for deserialization.
internal static readonly Assembly s_urtAssembly = Assembly.Load("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
internal static readonly string s_urtAssemblyString = s_urtAssembly.FullName!;
internal static readonly Assembly s_urtAlternativeAssembly = s_typeofString.Assembly;
internal static readonly string s_urtAlternativeAssemblyString = s_urtAlternativeAssembly.FullName!;
// Arrays
internal static readonly Type s_typeofTypeArray = typeof(Type[]);
internal static readonly Type s_typeofObjectArray = typeof(object[]);
internal static readonly Type s_typeofStringArray = typeof(string[]);
internal static readonly Type s_typeofBooleanArray = typeof(bool[]);
internal static readonly Type s_typeofByteArray = typeof(byte[]);
internal static readonly Type s_typeofCharArray = typeof(char[]);
internal static readonly Type s_typeofDecimalArray = typeof(decimal[]);
internal static readonly Type s_typeofDoubleArray = typeof(double[]);
internal static readonly Type s_typeofInt16Array = typeof(short[]);
internal static readonly Type s_typeofInt32Array = typeof(int[]);
internal static readonly Type s_typeofInt64Array = typeof(long[]);
internal static readonly Type s_typeofSByteArray = typeof(sbyte[]);
internal static readonly Type s_typeofSingleArray = typeof(float[]);
internal static readonly Type s_typeofTimeSpanArray = typeof(TimeSpan[]);
internal static readonly Type s_typeofDateTimeArray = typeof(DateTime[]);
internal static readonly Type s_typeofUInt16Array = typeof(ushort[]);
internal static readonly Type s_typeofUInt32Array = typeof(uint[]);
internal static readonly Type s_typeofUInt64Array = typeof(ulong[]);
internal static readonly Type s_typeofMarshalByRefObject = typeof(MarshalByRefObject);
private const int PrimitiveTypeEnumLength = 17; //Number of PrimitiveTypeEnums
private static volatile Type?[]? s_typeA;
private static volatile Type?[]? s_arrayTypeA;
private static volatile string?[]? s_valueA;
private static volatile TypeCode[]? s_typeCodeA;
private static volatile InternalPrimitiveTypeE[]? s_codeA;
internal static InternalPrimitiveTypeE ToCode(Type? type) =>
type == null ? ToPrimitiveTypeEnum(TypeCode.Empty) :
type.IsPrimitive ? ToPrimitiveTypeEnum(Type.GetTypeCode(type)) :
ReferenceEquals(type, s_typeofDateTime) ? InternalPrimitiveTypeE.DateTime :
ReferenceEquals(type, s_typeofTimeSpan) ? InternalPrimitiveTypeE.TimeSpan :
ReferenceEquals(type, s_typeofDecimal) ? InternalPrimitiveTypeE.Decimal :
InternalPrimitiveTypeE.Invalid;
internal static bool IsWriteAsByteArray(InternalPrimitiveTypeE code)
{
switch (code)
{
case InternalPrimitiveTypeE.Boolean:
case InternalPrimitiveTypeE.Char:
case InternalPrimitiveTypeE.Byte:
case InternalPrimitiveTypeE.Double:
case InternalPrimitiveTypeE.Int16:
case InternalPrimitiveTypeE.Int32:
case InternalPrimitiveTypeE.Int64:
case InternalPrimitiveTypeE.SByte:
case InternalPrimitiveTypeE.Single:
case InternalPrimitiveTypeE.UInt16:
case InternalPrimitiveTypeE.UInt32:
case InternalPrimitiveTypeE.UInt64:
return true;
default:
return false;
}
}
internal static int TypeLength(InternalPrimitiveTypeE code) =>
code switch
{
InternalPrimitiveTypeE.Boolean => 1,
InternalPrimitiveTypeE.Char => 2,
InternalPrimitiveTypeE.Byte => 1,
InternalPrimitiveTypeE.Double => 8,
InternalPrimitiveTypeE.Int16 => 2,
InternalPrimitiveTypeE.Int32 => 4,
InternalPrimitiveTypeE.Int64 => 8,
InternalPrimitiveTypeE.SByte => 1,
InternalPrimitiveTypeE.Single => 4,
InternalPrimitiveTypeE.UInt16 => 2,
InternalPrimitiveTypeE.UInt32 => 4,
InternalPrimitiveTypeE.UInt64 => 8,
_ => 0,
};
internal static Type? ToArrayType(InternalPrimitiveTypeE code)
{
if (s_arrayTypeA == null)
{
InitArrayTypeA();
}
return s_arrayTypeA![(int)code];
}
private static void InitTypeA()
{
var typeATemp = new Type?[PrimitiveTypeEnumLength];
typeATemp[(int)InternalPrimitiveTypeE.Invalid] = null;
typeATemp[(int)InternalPrimitiveTypeE.Boolean] = s_typeofBoolean;
typeATemp[(int)InternalPrimitiveTypeE.Byte] = s_typeofByte;
typeATemp[(int)InternalPrimitiveTypeE.Char] = s_typeofChar;
typeATemp[(int)InternalPrimitiveTypeE.Decimal] = s_typeofDecimal;
typeATemp[(int)InternalPrimitiveTypeE.Double] = s_typeofDouble;
typeATemp[(int)InternalPrimitiveTypeE.Int16] = s_typeofInt16;
typeATemp[(int)InternalPrimitiveTypeE.Int32] = s_typeofInt32;
typeATemp[(int)InternalPrimitiveTypeE.Int64] = s_typeofInt64;
typeATemp[(int)InternalPrimitiveTypeE.SByte] = s_typeofSByte;
typeATemp[(int)InternalPrimitiveTypeE.Single] = s_typeofSingle;
typeATemp[(int)InternalPrimitiveTypeE.TimeSpan] = s_typeofTimeSpan;
typeATemp[(int)InternalPrimitiveTypeE.DateTime] = s_typeofDateTime;
typeATemp[(int)InternalPrimitiveTypeE.UInt16] = s_typeofUInt16;
typeATemp[(int)InternalPrimitiveTypeE.UInt32] = s_typeofUInt32;
typeATemp[(int)InternalPrimitiveTypeE.UInt64] = s_typeofUInt64;
s_typeA = typeATemp;
}
private static void InitArrayTypeA()
{
var arrayTypeATemp = new Type?[PrimitiveTypeEnumLength];
arrayTypeATemp[(int)InternalPrimitiveTypeE.Invalid] = null;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Boolean] = s_typeofBooleanArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Byte] = s_typeofByteArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Char] = s_typeofCharArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Decimal] = s_typeofDecimalArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Double] = s_typeofDoubleArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Int16] = s_typeofInt16Array;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Int32] = s_typeofInt32Array;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Int64] = s_typeofInt64Array;
arrayTypeATemp[(int)InternalPrimitiveTypeE.SByte] = s_typeofSByteArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.Single] = s_typeofSingleArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.TimeSpan] = s_typeofTimeSpanArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.DateTime] = s_typeofDateTimeArray;
arrayTypeATemp[(int)InternalPrimitiveTypeE.UInt16] = s_typeofUInt16Array;
arrayTypeATemp[(int)InternalPrimitiveTypeE.UInt32] = s_typeofUInt32Array;
arrayTypeATemp[(int)InternalPrimitiveTypeE.UInt64] = s_typeofUInt64Array;
s_arrayTypeA = arrayTypeATemp;
}
internal static Type? ToType(InternalPrimitiveTypeE code)
{
if (s_typeA == null)
{
InitTypeA();
}
return s_typeA![(int)code];
}
internal static Array? CreatePrimitiveArray(InternalPrimitiveTypeE code, int length) =>
code switch
{
InternalPrimitiveTypeE.Boolean => new bool[length],
InternalPrimitiveTypeE.Byte => new byte[length],
InternalPrimitiveTypeE.Char => new char[length],
InternalPrimitiveTypeE.Decimal => new decimal[length],
InternalPrimitiveTypeE.Double => new double[length],
InternalPrimitiveTypeE.Int16 => new short[length],
InternalPrimitiveTypeE.Int32 => new int[length],
InternalPrimitiveTypeE.Int64 => new long[length],
InternalPrimitiveTypeE.SByte => new sbyte[length],
InternalPrimitiveTypeE.Single => new float[length],
InternalPrimitiveTypeE.TimeSpan => new TimeSpan[length],
InternalPrimitiveTypeE.DateTime => new DateTime[length],
InternalPrimitiveTypeE.UInt16 => new ushort[length],
InternalPrimitiveTypeE.UInt32 => new uint[length],
InternalPrimitiveTypeE.UInt64 => new ulong[length],
_ => null,
};
internal static bool IsPrimitiveArray(Type? type, [NotNullWhen(true)] out object? typeInformation)
{
if (ReferenceEquals(type, s_typeofBooleanArray)) typeInformation = InternalPrimitiveTypeE.Boolean;
else if (ReferenceEquals(type, s_typeofByteArray)) typeInformation = InternalPrimitiveTypeE.Byte;
else if (ReferenceEquals(type, s_typeofCharArray)) typeInformation = InternalPrimitiveTypeE.Char;
else if (ReferenceEquals(type, s_typeofDoubleArray)) typeInformation = InternalPrimitiveTypeE.Double;
else if (ReferenceEquals(type, s_typeofInt16Array)) typeInformation = InternalPrimitiveTypeE.Int16;
else if (ReferenceEquals(type, s_typeofInt32Array)) typeInformation = InternalPrimitiveTypeE.Int32;
else if (ReferenceEquals(type, s_typeofInt64Array)) typeInformation = InternalPrimitiveTypeE.Int64;
else if (ReferenceEquals(type, s_typeofSByteArray)) typeInformation = InternalPrimitiveTypeE.SByte;
else if (ReferenceEquals(type, s_typeofSingleArray)) typeInformation = InternalPrimitiveTypeE.Single;
else if (ReferenceEquals(type, s_typeofUInt16Array)) typeInformation = InternalPrimitiveTypeE.UInt16;
else if (ReferenceEquals(type, s_typeofUInt32Array)) typeInformation = InternalPrimitiveTypeE.UInt32;
else if (ReferenceEquals(type, s_typeofUInt64Array)) typeInformation = InternalPrimitiveTypeE.UInt64;
else
{
typeInformation = null;
return false;
}
return true;
}
private static void InitValueA()
{
var valueATemp = new string?[PrimitiveTypeEnumLength];
valueATemp[(int)InternalPrimitiveTypeE.Invalid] = null;
valueATemp[(int)InternalPrimitiveTypeE.Boolean] = "Boolean";
valueATemp[(int)InternalPrimitiveTypeE.Byte] = "Byte";
valueATemp[(int)InternalPrimitiveTypeE.Char] = "Char";
valueATemp[(int)InternalPrimitiveTypeE.Decimal] = "Decimal";
valueATemp[(int)InternalPrimitiveTypeE.Double] = "Double";
valueATemp[(int)InternalPrimitiveTypeE.Int16] = "Int16";
valueATemp[(int)InternalPrimitiveTypeE.Int32] = "Int32";
valueATemp[(int)InternalPrimitiveTypeE.Int64] = "Int64";
valueATemp[(int)InternalPrimitiveTypeE.SByte] = "SByte";
valueATemp[(int)InternalPrimitiveTypeE.Single] = "Single";
valueATemp[(int)InternalPrimitiveTypeE.TimeSpan] = "TimeSpan";
valueATemp[(int)InternalPrimitiveTypeE.DateTime] = "DateTime";
valueATemp[(int)InternalPrimitiveTypeE.UInt16] = "UInt16";
valueATemp[(int)InternalPrimitiveTypeE.UInt32] = "UInt32";
valueATemp[(int)InternalPrimitiveTypeE.UInt64] = "UInt64";
s_valueA = valueATemp;
}
internal static string? ToComType(InternalPrimitiveTypeE code)
{
if (s_valueA == null)
{
InitValueA();
}
return s_valueA![(int)code];
}
private static void InitTypeCodeA()
{
var typeCodeATemp = new TypeCode[PrimitiveTypeEnumLength];
typeCodeATemp[(int)InternalPrimitiveTypeE.Invalid] = TypeCode.Object;
typeCodeATemp[(int)InternalPrimitiveTypeE.Boolean] = TypeCode.Boolean;
typeCodeATemp[(int)InternalPrimitiveTypeE.Byte] = TypeCode.Byte;
typeCodeATemp[(int)InternalPrimitiveTypeE.Char] = TypeCode.Char;
typeCodeATemp[(int)InternalPrimitiveTypeE.Decimal] = TypeCode.Decimal;
typeCodeATemp[(int)InternalPrimitiveTypeE.Double] = TypeCode.Double;
typeCodeATemp[(int)InternalPrimitiveTypeE.Int16] = TypeCode.Int16;
typeCodeATemp[(int)InternalPrimitiveTypeE.Int32] = TypeCode.Int32;
typeCodeATemp[(int)InternalPrimitiveTypeE.Int64] = TypeCode.Int64;
typeCodeATemp[(int)InternalPrimitiveTypeE.SByte] = TypeCode.SByte;
typeCodeATemp[(int)InternalPrimitiveTypeE.Single] = TypeCode.Single;
typeCodeATemp[(int)InternalPrimitiveTypeE.TimeSpan] = TypeCode.Object;
typeCodeATemp[(int)InternalPrimitiveTypeE.DateTime] = TypeCode.DateTime;
typeCodeATemp[(int)InternalPrimitiveTypeE.UInt16] = TypeCode.UInt16;
typeCodeATemp[(int)InternalPrimitiveTypeE.UInt32] = TypeCode.UInt32;
typeCodeATemp[(int)InternalPrimitiveTypeE.UInt64] = TypeCode.UInt64;
s_typeCodeA = typeCodeATemp;
}
// Returns a System.TypeCode from a InternalPrimitiveTypeE
internal static TypeCode ToTypeCode(InternalPrimitiveTypeE code)
{
if (s_typeCodeA == null)
{
InitTypeCodeA();
}
return s_typeCodeA![(int)code];
}
private static void InitCodeA()
{
var codeATemp = new InternalPrimitiveTypeE[19];
codeATemp[(int)TypeCode.Empty] = InternalPrimitiveTypeE.Invalid;
codeATemp[(int)TypeCode.Object] = InternalPrimitiveTypeE.Invalid;
codeATemp[(int)TypeCode.DBNull] = InternalPrimitiveTypeE.Invalid;
codeATemp[(int)TypeCode.Boolean] = InternalPrimitiveTypeE.Boolean;
codeATemp[(int)TypeCode.Char] = InternalPrimitiveTypeE.Char;
codeATemp[(int)TypeCode.SByte] = InternalPrimitiveTypeE.SByte;
codeATemp[(int)TypeCode.Byte] = InternalPrimitiveTypeE.Byte;
codeATemp[(int)TypeCode.Int16] = InternalPrimitiveTypeE.Int16;
codeATemp[(int)TypeCode.UInt16] = InternalPrimitiveTypeE.UInt16;
codeATemp[(int)TypeCode.Int32] = InternalPrimitiveTypeE.Int32;
codeATemp[(int)TypeCode.UInt32] = InternalPrimitiveTypeE.UInt32;
codeATemp[(int)TypeCode.Int64] = InternalPrimitiveTypeE.Int64;
codeATemp[(int)TypeCode.UInt64] = InternalPrimitiveTypeE.UInt64;
codeATemp[(int)TypeCode.Single] = InternalPrimitiveTypeE.Single;
codeATemp[(int)TypeCode.Double] = InternalPrimitiveTypeE.Double;
codeATemp[(int)TypeCode.Decimal] = InternalPrimitiveTypeE.Decimal;
codeATemp[(int)TypeCode.DateTime] = InternalPrimitiveTypeE.DateTime;
codeATemp[17] = InternalPrimitiveTypeE.Invalid;
codeATemp[(int)TypeCode.String] = InternalPrimitiveTypeE.Invalid;
s_codeA = codeATemp;
}
// Returns a InternalPrimitiveTypeE from a System.TypeCode
internal static InternalPrimitiveTypeE ToPrimitiveTypeEnum(TypeCode typeCode)
{
if (s_codeA == null)
{
InitCodeA();
}
return s_codeA![(int)typeCode];
}
// Translates a string into an Object
internal static object? FromString(string? value, InternalPrimitiveTypeE code)
{
// InternalPrimitiveTypeE needs to be a primitive type
Debug.Assert((code != InternalPrimitiveTypeE.Invalid), "[Converter.FromString]!InternalPrimitiveTypeE.Invalid ");
return code != InternalPrimitiveTypeE.Invalid ?
Convert.ChangeType(value, ToTypeCode(code), CultureInfo.InvariantCulture) :
value;
}
}
}
|