Files
mxaccess/analysis/decompiled/aaServicesContractIAuthenticateASB/Asb.Base.V2/Value.cs
T
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
Layout:
- src/                    .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
                          MxAsbClient, probes, tests, harnesses. Executable spec.
- design/                 Architectural plan for the Rust port (M0–M6), error
                          model, protocol invariants, risks (R1–R16), adversarial
                          review log (review.md).
- rust/                   Rust workspace. M0 skeleton + M1 codec parity.
                          mxaccess-codec: 215 unit tests + 2 cross-implementation
                          parity tests (byte-identical against .NET reference).
                          Other crates are M0 stubs awaiting M2+.
- captures/               Frida + netsh + pcap evidence per CLAUDE.md
                          ("captures are evidence, not throwaway logs").
- analysis/               Decompiled C# (frida/proxy/decompiled-*),
                          Ghidra exports for native DLLs (`exports/` only —
                          working state at `projects/` and AVEVA's input
                          binaries at `input/` are gitignored).
- docs/                   Reverse-engineering reference docs.
- tools/                  Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
                          Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/      Rust CI: fmt + build + test + clippy on Windows.
- LICENSE                 MIT (Joseph Doherty, 2026).

Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly

Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:21:00 -04:00

1394 lines
30 KiB
C#

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<Value>
{
[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<byte> list = new List<byte>();
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<byte> list = new List<byte>();
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<ushort, int, byte[]> 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<ushort, int, byte[]> 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;
}
}