using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Xml.Serialization; using ArchestrAServices.ASBContract; using ArchestrAServices.Common; using Asb.Base.V2.Serialization; namespace Asb.Base.V2; [DebuggerDisplay("{Item}")] public sealed class Value : IBaseV2CustomSerializable, IEquatable { [XmlIgnore] public object Item { get; private set; } [XmlIgnore] public ValueItemType ItemType { get; private set; } [XmlIgnore] public bool IsArray { get; private set; } [XmlIgnore] public ushort MxLegacyItemType { get; private set; } [XmlIgnore] public int MxLegacyLength { get; private set; } [XmlElement(ElementName = "Payload", DataType = "base64Binary", IsNullable = true, Order = 0)] public byte[] Payload { get { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter writer = new BinaryWriter(memoryStream); ((IBaseV2CustomSerializable)this).WriteToStream(writer); return memoryStream.ToArray(); } set { using MemoryStream input = new MemoryStream(value); using BinaryReader reader = new BinaryReader(input); ((IBaseV2CustomSerializable)this).InitializeFromStream(reader); } } [XmlIgnore] public DataType MxLegacyDataType { get { switch (ItemType) { case ValueItemType.Boolean: if (!IsArray) { return DataType.TypeBool; } return DataType.TypeBoolArray; case ValueItemType.Byte: if (!IsArray) { return DataType.TypeByte; } return DataType.TypeByteArray; case ValueItemType.SignedByte: if (!IsArray) { return DataType.TypeSByte; } return DataType.TypeSByteArray; case ValueItemType.Short: if (!IsArray) { return DataType.TypeInt16; } return DataType.TypeInt16Array; case ValueItemType.UnsignedShort: if (!IsArray) { return DataType.TypeUInt16; } return DataType.TypeUInt16Array; case ValueItemType.Int: if (!IsArray) { return DataType.TypeInt32; } return DataType.TypeInt32Array; case ValueItemType.UnsignedInt: if (!IsArray) { return DataType.TypeUInt32; } return DataType.TypeUInt32Array; case ValueItemType.Long: if (!IsArray) { return DataType.TypeInt64; } return DataType.TypeInt64Array; case ValueItemType.UnsignedLong: if (!IsArray) { return DataType.TypeUInt64; } return DataType.TypeUInt64Array; case ValueItemType.Single: if (!IsArray) { return DataType.TypeFloat; } return DataType.TypeFloatArray; case ValueItemType.Double: if (!IsArray) { return DataType.TypeDouble; } return DataType.TypeDoubleArray; case ValueItemType.DateTime: if (!IsArray) { return DataType.TypeDateTime; } return DataType.TypeDateTimeArray; case ValueItemType.Duration: if (!IsArray) { return DataType.TypeDuration; } return DataType.TypeDurationArray; case ValueItemType.Guid: if (!IsArray) { return DataType.TypeGuid; } return DataType.TypeGuidArray; case ValueItemType.String: if (!IsArray) { return DataType.TypeString; } return DataType.TypeStringArray; default: return ASBEnumFactory.IntToDataType(MxLegacyItemType); } } } public static Value Create(object value) { if (value == null) { return new Value(); } ValueItemType? valueItemType = ClrTypeToValueType(value.GetType()); if (!valueItemType.HasValue) { throw new ArgumentException("value is not a supported type", "value"); } return new Value { Item = value, ItemType = valueItemType.Value, IsArray = (value is Array) }; } public static Value Create(bool value) { return new Value { Item = value, ItemType = ValueItemType.Boolean, IsArray = false }; } public static Value Create(byte value) { return new Value { Item = value, ItemType = ValueItemType.Byte, IsArray = false }; } public static Value Create(sbyte value) { return new Value { Item = value, ItemType = ValueItemType.SignedByte, IsArray = false }; } public static Value Create(short value) { return new Value { Item = value, ItemType = ValueItemType.Short, IsArray = false }; } public static Value Create(ushort value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedShort, IsArray = false }; } public static Value Create(int value) { return new Value { Item = value, ItemType = ValueItemType.Int, IsArray = false }; } public static Value Create(uint value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedInt, IsArray = false }; } public static Value Create(long value) { return new Value { Item = value, ItemType = ValueItemType.Long, IsArray = false }; } public static Value Create(ulong value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedLong, IsArray = false }; } public static Value Create(float value) { return new Value { Item = value, ItemType = ValueItemType.Single, IsArray = false }; } public static Value Create(double value) { return new Value { Item = value, ItemType = ValueItemType.Double, IsArray = false }; } public static Value Create(decimal value) { return new Value { Item = value, ItemType = ValueItemType.Decimal, IsArray = false }; } public static Value Create(string value) { if (value == null) { throw new ArgumentNullException("value"); } return new Value { Item = value, ItemType = ValueItemType.String, IsArray = false }; } public static Value Create(DateTime value) { return new Value { Item = value, ItemType = ValueItemType.DateTime, IsArray = false }; } public static Value Create(TimeSpan value) { return new Value { Item = value, ItemType = ValueItemType.Duration, IsArray = false }; } public static Value Create(Guid value) { return new Value { Item = value, ItemType = ValueItemType.Guid, IsArray = false }; } public static Value Create(bool[] value) { return new Value { Item = value, ItemType = ValueItemType.Boolean, IsArray = true }; } public static Value Create(byte[] value) { return new Value { Item = value, ItemType = ValueItemType.Byte, IsArray = true }; } public static Value Create(sbyte[] value) { return new Value { Item = value, ItemType = ValueItemType.SignedByte, IsArray = true }; } public static Value Create(short[] value) { return new Value { Item = value, ItemType = ValueItemType.Short, IsArray = true }; } public static Value Create(ushort[] value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedShort, IsArray = true }; } public static Value Create(int[] value) { return new Value { Item = value, ItemType = ValueItemType.Int, IsArray = true }; } public static Value Create(uint[] value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedInt, IsArray = true }; } public static Value Create(long[] value) { return new Value { Item = value, ItemType = ValueItemType.Long, IsArray = true }; } public static Value Create(ulong[] value) { return new Value { Item = value, ItemType = ValueItemType.UnsignedLong, IsArray = true }; } public static Value Create(float[] value) { return new Value { Item = value, ItemType = ValueItemType.Single, IsArray = true }; } public static Value Create(double[] value) { return new Value { Item = value, ItemType = ValueItemType.Double, IsArray = true }; } public static Value Create(decimal[] value) { return new Value { Item = value, ItemType = ValueItemType.Decimal, IsArray = true }; } public static Value Create(string[] value) { return new Value { Item = value, ItemType = ValueItemType.String, IsArray = true }; } public static Value Create(DateTime[] value) { return new Value { Item = value, ItemType = ValueItemType.DateTime, IsArray = true }; } public static Value Create(TimeSpan[] value) { return new Value { Item = value, ItemType = ValueItemType.Duration, IsArray = true }; } public static Value Create(Guid[] value) { return new Value { Item = value, ItemType = ValueItemType.Guid, IsArray = true }; } public static Value CreateMxLegacy(ushort mxLegacyType, int mxLegacyLength, byte[] mxLegacyPayload) { return new Value { Item = mxLegacyPayload, ItemType = ValueItemType.MxLegacy, IsArray = false, MxLegacyLength = mxLegacyLength, MxLegacyItemType = mxLegacyType }; } public static Value Create(CustomEnum customEnum) { if (customEnum == null) { throw new ArgumentNullException("customEnum"); } short ordinal = customEnum.Ordinal; string ordinalValue = customEnum.OrdinalValue; ushort mxLegacyType = ASBEnumFactory.DataTypeToInt(DataType.TypeEnum); List list = new List(); list.AddRange(BitConverter.GetBytes(Convert.ToInt16(ordinal))); list.AddRange(BitConverter.GetBytes(Convert.ToUInt32(ordinalValue.Length))); list.AddRange(Encoding.Unicode.GetBytes(ordinalValue)); int mxLegacyLength = 6 + ordinalValue.Length; byte[] mxLegacyPayload = list.ToArray(); return CreateMxLegacy(mxLegacyType, mxLegacyLength, mxLegacyPayload); } public static Value Create(CustomEnum[] customEnums) { int num = 0; List list = new List(); if (customEnums != null && customEnums.Length != 0) { CustomEnum[] array = customEnums; foreach (CustomEnum obj in array) { short ordinal = obj.Ordinal; string ordinalValue = obj.OrdinalValue; num += 6 + ordinalValue.Length; list.AddRange(BitConverter.GetBytes(Convert.ToInt16(ordinal))); list.AddRange(BitConverter.GetBytes(Convert.ToUInt32(ordinalValue.Length))); list.AddRange(Encoding.Unicode.GetBytes(ordinalValue)); } int mxLegacyLength = num; byte[] mxLegacyPayload = list.ToArray(); return CreateMxLegacy(ASBEnumFactory.DataTypeToInt(DataType.TypeEnumArray), mxLegacyLength, mxLegacyPayload); } return CreateMxLegacy(ASBEnumFactory.DataTypeToInt(DataType.TypeEnum), 0, new byte[0]); } public bool Equals(Value other) { if (other == null) { return false; } if (other == this) { return true; } if (ItemType != other.ItemType || IsArray != other.IsArray) { return false; } if (IsArray) { if (Item == other.Item) { return true; } if (Item == null || other.Item == null) { return false; } return ((IStructuralEquatable)Item).Equals(other.Item, StructuralComparisons.StructuralEqualityComparer); } return object.Equals(Item, other.Item); } public override bool Equals(object obj) { return Equals(obj as Value); } public override int GetHashCode() { return Item?.GetHashCode() ?? 0; } void IBaseV2CustomSerializable.InitializeFromStream(BinaryReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } ItemType = (ValueItemType)reader.ReadInt32(); IsArray = reader.ReadBoolean(); if (IsArray) { if (reader.ReadBoolean()) { Item = null; return; } int num = reader.ReadInt32(); Array array = Array.CreateInstance(ValueTypeToClrType(ItemType), num); for (int i = 0; i < num; i++) { array.SetValue(ReadContent(reader, ItemType), i); } Item = array; } else if (ItemType == ValueItemType.MxLegacy) { Tuple tuple = ReadMxLegacyContent(reader); MxLegacyItemType = tuple.Item1; MxLegacyLength = tuple.Item2; Item = tuple.Item3; } else { Item = ReadContent(reader, ItemType); } } void IBaseV2CustomSerializable.WriteToStream(BinaryWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } writer.Write((int)ItemType); writer.Write(IsArray); if (IsArray) { Array array = (Array)Item; if (array != null) { writer.Write(value: false); writer.Write(array.Length); { foreach (object item in array) { WriteContent(writer, item, ItemType); } return; } } writer.Write(value: true); } else if (ItemType == ValueItemType.MxLegacy) { WriteMxLegacyContent(writer, MxLegacyItemType, MxLegacyLength, (byte[])Item); } else { WriteContent(writer, Item, ItemType); } } void IBaseV2CustomSerializable.WriteArrayToStream(object graph, BinaryWriter writer) { if (graph == null || writer == null) { return; } try { if (graph is Value[] array) { writer.Write(array.Length); Value[] array2 = array; for (int i = 0; i < array2.Length; i++) { ((IBaseV2CustomSerializable)array2[i]).WriteToStream(writer); } } } catch (Exception ex) { ServiceTrace.LogError("Exception caught serializing an array of Value objects: {0}", ex.Message); } } object IBaseV2CustomSerializable.InitializeArrayFromStream(BinaryReader reader, int arrayLength) { if (reader == null) { return null; } Value[] result = null; try { Value[] array = new Value[arrayLength]; for (int i = 0; i < arrayLength; i++) { ((IBaseV2CustomSerializable)array[i]).InitializeFromStream(reader); } result = array; } catch (Exception ex) { ServiceTrace.LogError("Exception caught deserializing an array of ASBStatus objects: {0}", ex.Message); } return result; } public object ReadByte() { if (ItemType == ValueItemType.Byte) { return (byte)Item; } return MxValueHelper.ReadByte(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadShort() { if (ItemType == ValueItemType.Short) { return (short)Item; } return MxValueHelper.ReadShort(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedShort() { if (ItemType == ValueItemType.UnsignedShort) { return (ushort)Item; } return MxValueHelper.ReadUnsignedShort(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadInt() { if (ItemType == ValueItemType.Int) { return (int)Item; } return MxValueHelper.ReadInt(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedInt() { if (ItemType == ValueItemType.UnsignedInt) { return (uint)Item; } return MxValueHelper.ReadUnsignedInt(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadLong() { if (ItemType == ValueItemType.Long) { return (long)Item; } return MxValueHelper.ReadLong(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedLong() { if (ItemType == ValueItemType.UnsignedLong) { return (ulong)Item; } return MxValueHelper.ReadUnsignedLong(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadSingle() { if (ItemType == ValueItemType.Single) { return (float)Item; } return MxValueHelper.ReadSingle(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDouble() { if (ItemType == ValueItemType.Double) { return (double)Item; } return MxValueHelper.ReadDouble(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadString() { if (ItemType == ValueItemType.String) { return (string)Item; } return MxValueHelper.ReadDouble(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadBoolean() { if (ItemType == ValueItemType.Boolean) { return (bool)Item; } return MxValueHelper.ReadBoolean(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadSignedByte() { if (ItemType == ValueItemType.SignedByte) { return (sbyte)Item; } return MxValueHelper.ReadSignedByte(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDateTime() { if (ItemType == ValueItemType.DateTime) { return (DateTime)Item; } return MxValueHelper.ReadDateTime(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDuration() { if (ItemType == ValueItemType.Duration) { return (TimeSpan)Item; } return MxValueHelper.ReadDuration(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadGuid() { if (ItemType == ValueItemType.Guid) { return (Guid)Item; } return MxValueHelper.ReadGuid(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public byte[] ReadByteString() { return (byte[])Item; } public string ReadLocalizedText() { return (string)ReadString(); } public object GetScalarValue(DataType targetType) { object obj = null; try { switch (ASBEnumFactory.IntToDataType(MxLegacyItemType)) { case DataType.TypeBool: obj = ReadBoolean(); return (DataType.TypeBool == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeByte: obj = ReadByte(); return (targetType == DataType.TypeByte) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeDateTime: obj = ReadDateTime(); return (targetType == DataType.TypeByte) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeDouble: obj = ReadDouble(); return (DataType.TypeDouble == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeDuration: obj = ReadDuration(); return (DataType.TypeDuration == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeFloat: obj = ReadSingle(); return (DataType.TypeFloat == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeGuid: obj = ReadGuid(); return (DataType.TypeGuid == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeInt16: obj = ReadShort(); return (DataType.TypeInt16 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeInt32: obj = ReadInt(); return (DataType.TypeInt32 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeInt64: obj = ReadLong(); return (DataType.TypeInt64 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeLocalizedText: obj = ReadLocalizedText(); return (DataType.TypeLocalizedText == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeSByte: obj = ReadSignedByte(); return (DataType.TypeSByte == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeString: obj = ReadString(); return (DataType.TypeString == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeUInt16: obj = ReadUnsignedShort(); return (DataType.TypeUInt16 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeUInt32: obj = ReadUnsignedInt(); return (DataType.TypeUInt32 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); case DataType.TypeUInt64: obj = ReadUnsignedLong(); return (DataType.TypeUInt64 == targetType) ? obj : MxValueHelper.GetValueInTargetType(targetType, obj); default: return ReadString(); } } catch (Exception) { return obj; } } public object GetValueInTargetArrayType(DataType targetType) { switch (targetType) { case DataType.TypeBool: { bool[] array14 = (bool[])ReadBooleanArray(); if (array14 == null || array14.Length == 0) { return null; } return array14; } case DataType.TypeByte: { byte[] array8 = (byte[])ReadByteArray(); if (array8 == null || array8.Length == 0) { return null; } return array8; } case DataType.TypeDateTime: { DateTime[] array15 = (DateTime[])ReadDateTimeArray(); if (array15 == null || array15.Length == 0) { return null; } return array15; } case DataType.TypeDouble: { double[] array11 = (double[])ReadDoubleArray(); if (array11 == null || array11.Length == 0) { return null; } return array11; } case DataType.TypeDuration: { TimeSpan[] array6 = (TimeSpan[])ReadDurationArray(); if (array6 == null || array6.Length == 0) { return null; } return array6; } case DataType.TypeFloat: { float[] array12 = (float[])ReadSingleArray(); if (array12 == null || array12.Length == 0) { return null; } return array12; } case DataType.TypeGuid: { Guid[] array10 = (Guid[])ReadGuidArray(); if (array10 == null || array10.Length == 0) { return null; } return array10; } case DataType.TypeInt16: { short[] array3 = (short[])ReadShortArray(); if (array3 == null || array3.Length == 0) { return null; } return array3; } case DataType.TypeInt32: { int[] array4 = (int[])ReadIntegerArray(); if (array4 == null || array4.Length == 0) { return null; } return array4; } case DataType.TypeInt64: { long[] array7 = (long[])ReadLongArray(); if (array7 == null || array7.Length == 0) { return null; } return array7; } case DataType.TypeSByte: { sbyte[] array2 = (sbyte[])ReadSignedByteArray(); if (array2 == null || array2.Length == 0) { return null; } return array2; } case DataType.TypeUInt16: { ushort[] array13 = (ushort[])ReadUnsignedShortArray(); if (array13 == null || array13.Length == 0) { return null; } return array13; } case DataType.TypeUInt32: { uint[] array9 = (uint[])ReadUnsignedIntArray(); if (array9 == null || array9.Length == 0) { return null; } return array9; } case DataType.TypeUInt64: { ulong[] array5 = (ulong[])ReadUnsignedLongArray(); if (array5 == null || array5.Length == 0) { return null; } return array5; } default: { string[] array = (string[])ReadStringArray(); if (array == null || array.Length == 0) { return null; } return array; } } } public object GetArrayValue(DataType targetType) { try { return GetValueInTargetArrayType(targetType); } catch (Exception) { return null; } } public object ReadEnum() { return MxValueHelper.ReadEnum(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadIntegerArray() { if (ItemType == ValueItemType.Int && IsArray) { return (int[])Item; } return MxValueHelper.ReadIntegerArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadByteArray() { if (ItemType == ValueItemType.Byte && IsArray) { return (byte[])Item; } return MxValueHelper.ReadByteArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public char[] ReadCharArray() { return MxValueHelper.ReadCharArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadShortArray() { if (ItemType == ValueItemType.Short && IsArray) { return (short[])Item; } return MxValueHelper.ReadShortArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedShortArray() { if (ItemType == ValueItemType.UnsignedShort && IsArray) { return (ushort[])Item; } return MxValueHelper.ReadUnsignedShortArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedIntArray() { if (ItemType == ValueItemType.UnsignedInt && IsArray) { return (uint[])Item; } return MxValueHelper.ReadUnsignedIntArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadLongArray() { if (ItemType == ValueItemType.Long && IsArray) { return (long[])Item; } return MxValueHelper.ReadLongArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadUnsignedLongArray() { if (ItemType == ValueItemType.UnsignedLong && IsArray) { return (ulong[])Item; } return MxValueHelper.ReadUnsignedLongArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadSingleArray() { if (ItemType == ValueItemType.Single && IsArray) { return (float[])Item; } return MxValueHelper.ReadSingleArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDoubleArray() { if (ItemType == ValueItemType.Double && IsArray) { return (double[])Item; } return MxValueHelper.ReadDoubleArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadStringArray() { if (ItemType == ValueItemType.String && IsArray) { return (string[])Item; } return MxValueHelper.ReadStringArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDateTimeArray() { if (ItemType == ValueItemType.DateTime && IsArray) { return (DateTime[])Item; } return MxValueHelper.ReadDateTimeArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadDurationArray() { if (ItemType == ValueItemType.Duration && IsArray) { return (TimeSpan[])Item; } return MxValueHelper.ReadDurationArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadGuidArray() { if (ItemType == ValueItemType.Guid && IsArray) { return (Guid[])Item; } return MxValueHelper.ReadGuidArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadBooleanArray() { if (ItemType == ValueItemType.Boolean && IsArray) { return (bool[])Item; } return MxValueHelper.ReadBooleanArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadSignedByteArray() { if (ItemType == ValueItemType.SignedByte && IsArray) { return (sbyte[])Item; } return MxValueHelper.ReadSignedByteArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } public object ReadEnumArray() { return MxValueHelper.ReadEnumArray(MxLegacyItemType, MxLegacyLength, (byte[])Item); } private static object ReadContent(BinaryReader reader, ValueItemType valueType) { return valueType switch { ValueItemType.None => null, ValueItemType.Boolean => reader.ReadBoolean(), ValueItemType.Byte => reader.ReadByte(), ValueItemType.SignedByte => reader.ReadSByte(), ValueItemType.Short => reader.ReadInt16(), ValueItemType.UnsignedShort => reader.ReadUInt16(), ValueItemType.Int => reader.ReadInt32(), ValueItemType.UnsignedInt => reader.ReadUInt32(), ValueItemType.Long => reader.ReadInt64(), ValueItemType.UnsignedLong => reader.ReadUInt64(), ValueItemType.Single => reader.ReadSingle(), ValueItemType.Double => reader.ReadDouble(), ValueItemType.Decimal => reader.ReadDecimal(), ValueItemType.DateTime => DateTime.FromFileTimeUtc(reader.ReadInt64()), ValueItemType.Duration => TimeSpan.FromTicks(reader.ReadInt64()), ValueItemType.Guid => new Guid(reader.ReadBytes(16)), ValueItemType.String => reader.ReadStringSafe(), _ => throw new NotSupportedException("Unsupported ItemType"), }; } private static void WriteContent(BinaryWriter writer, object value, ValueItemType valueType) { switch (valueType) { case ValueItemType.Boolean: writer.Write((bool)value); break; case ValueItemType.Byte: writer.Write((byte)value); break; case ValueItemType.SignedByte: writer.Write((sbyte)value); break; case ValueItemType.Short: writer.Write((short)value); break; case ValueItemType.UnsignedShort: writer.Write((ushort)value); break; case ValueItemType.Int: writer.Write((int)value); break; case ValueItemType.UnsignedInt: writer.Write((uint)value); break; case ValueItemType.Long: writer.Write((long)value); break; case ValueItemType.UnsignedLong: writer.Write((ulong)value); break; case ValueItemType.Single: writer.Write((float)value); break; case ValueItemType.Double: writer.Write((double)value); break; case ValueItemType.Decimal: writer.Write((decimal)value); break; case ValueItemType.DateTime: writer.Write(((DateTime)value).ToFileTimeUtc()); break; case ValueItemType.Duration: writer.Write(((TimeSpan)value).Ticks); break; case ValueItemType.Guid: writer.Write(((Guid)value).ToByteArray()); break; case ValueItemType.String: writer.WriteStringSafe((string)value); break; default: throw new NotSupportedException("Unsupported ItemType"); case ValueItemType.None: break; } } private static void WriteMxLegacyContent(BinaryWriter writer, ushort mxLegacyDataType, int mxLegacyLength, byte[] mxLegacyPayload) { writer.Write(mxLegacyDataType); writer.Write(mxLegacyLength); writer.Write(mxLegacyPayload.Length); writer.Write(mxLegacyPayload); } private static Tuple ReadMxLegacyContent(BinaryReader reader) { ushort item = reader.ReadUInt16(); int item2 = reader.ReadInt32(); int count = reader.ReadInt32(); return Tuple.Create(item, item2, reader.ReadBytes(count)); } private static Type ValueTypeToClrType(ValueItemType valueType) { return valueType switch { ValueItemType.Boolean => typeof(bool), ValueItemType.Byte => typeof(byte), ValueItemType.SignedByte => typeof(sbyte), ValueItemType.Int => typeof(int), ValueItemType.UnsignedInt => typeof(uint), ValueItemType.Short => typeof(short), ValueItemType.UnsignedShort => typeof(ushort), ValueItemType.Long => typeof(long), ValueItemType.UnsignedLong => typeof(ulong), ValueItemType.Single => typeof(float), ValueItemType.Decimal => typeof(decimal), ValueItemType.Double => typeof(double), ValueItemType.DateTime => typeof(DateTime), ValueItemType.Duration => typeof(TimeSpan), ValueItemType.Guid => typeof(Guid), ValueItemType.String => typeof(string), _ => throw new NotSupportedException("Unsupported type of the item"), }; } private static ValueItemType? ClrTypeToValueType(Type type) { if (type.IsArray) { type = type.GetElementType(); } switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: return ValueItemType.Boolean; case TypeCode.Byte: return ValueItemType.Byte; case TypeCode.SByte: return ValueItemType.SignedByte; case TypeCode.Int16: return ValueItemType.Short; case TypeCode.UInt16: return ValueItemType.UnsignedShort; case TypeCode.Int32: return ValueItemType.Int; case TypeCode.UInt32: return ValueItemType.UnsignedInt; case TypeCode.Int64: return ValueItemType.Long; case TypeCode.UInt64: return ValueItemType.UnsignedLong; case TypeCode.Single: return ValueItemType.Single; case TypeCode.Double: return ValueItemType.Double; case TypeCode.Decimal: return ValueItemType.Decimal; case TypeCode.DateTime: return ValueItemType.DateTime; case TypeCode.String: return ValueItemType.String; case TypeCode.Object: if (type == typeof(TimeSpan)) { return ValueItemType.Duration; } if (type == typeof(Guid)) { return ValueItemType.Guid; } break; } return null; } }