Files
PURErat-crack-scode/decompiled/PanelPlugins/PureHelper.Client/ProtoBuf.Meta/ValueMember.cs
T
2026-08-27 10:56:38 -06:00

853 lines
22 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using ProtoBuf.Serializers;
namespace ProtoBuf.Meta;
public class ValueMember
{
internal sealed class Comparer : IComparer, IComparer<ValueMember>
{
public static readonly Comparer Default = new Comparer();
public int Compare(object x, object y)
{
return Compare(x as ValueMember, y as ValueMember);
}
public int Compare(ValueMember x, ValueMember y)
{
if (x == y)
{
return 0;
}
if (x == null)
{
return -1;
}
if (y == null)
{
return 1;
}
return x.FieldNumber.CompareTo(y.FieldNumber);
}
}
private int _fieldNumber;
private readonly MemberInfo originalMember;
private MemberInfo backingMember;
private readonly Type parentType;
private readonly Type itemType;
private readonly Type defaultType;
private readonly Type memberType;
private object defaultValue;
private readonly RuntimeTypeModel model;
private IProtoSerializer serializer;
private DataFormat dataFormat;
private DataFormat mapKeyFormat;
private DataFormat mapValueFormat;
private MethodInfo getSpecified;
private MethodInfo setSpecified;
private string name;
private const byte OPTIONS_IsStrict = 1;
private const byte OPTIONS_IsPacked = 2;
private const byte OPTIONS_IsRequired = 4;
private const byte OPTIONS_OverwriteList = 8;
private const byte OPTIONS_SupportNull = 16;
private const byte OPTIONS_AsReference = 32;
private const byte OPTIONS_IsMap = 64;
private const byte OPTIONS_DynamicType = 128;
private byte flags;
public int FieldNumber
{
get
{
return _fieldNumber;
}
internal set
{
if (_fieldNumber != value)
{
MetaType.AssertValidFieldNumber(value);
ThrowIfFrozen();
_fieldNumber = value;
}
}
}
public MemberInfo Member => originalMember;
public MemberInfo BackingMember
{
get
{
return backingMember;
}
set
{
if ((object)backingMember != value)
{
ThrowIfFrozen();
backingMember = value;
}
}
}
public Type ItemType => itemType;
public Type MemberType => memberType;
public Type DefaultType => defaultType;
public Type ParentType => parentType;
public object DefaultValue
{
get
{
return defaultValue;
}
set
{
if (defaultValue != value)
{
ThrowIfFrozen();
defaultValue = value;
}
}
}
internal IProtoSerializer Serializer => serializer ?? (serializer = BuildSerializer());
public DataFormat DataFormat
{
get
{
return dataFormat;
}
set
{
if (value != dataFormat)
{
ThrowIfFrozen();
dataFormat = value;
}
}
}
public bool IsStrict
{
get
{
return HasFlag(1);
}
set
{
SetFlag(1, value, throwIfFrozen: true);
}
}
public bool IsPacked
{
get
{
return HasFlag(2);
}
set
{
SetFlag(2, value, throwIfFrozen: true);
}
}
public bool OverwriteList
{
get
{
return HasFlag(8);
}
set
{
SetFlag(8, value, throwIfFrozen: true);
}
}
public bool IsRequired
{
get
{
return HasFlag(4);
}
set
{
SetFlag(4, value, throwIfFrozen: true);
}
}
public bool AsReference
{
get
{
return HasFlag(32);
}
set
{
SetFlag(32, value, throwIfFrozen: true);
}
}
public bool DynamicType
{
get
{
return HasFlag(128);
}
set
{
SetFlag(128, value, throwIfFrozen: true);
}
}
public bool IsMap
{
get
{
return HasFlag(64);
}
set
{
SetFlag(64, value, throwIfFrozen: true);
}
}
public DataFormat MapKeyFormat
{
get
{
return mapKeyFormat;
}
set
{
if (mapKeyFormat != value)
{
ThrowIfFrozen();
mapKeyFormat = value;
}
}
}
public DataFormat MapValueFormat
{
get
{
return mapValueFormat;
}
set
{
if (mapValueFormat != value)
{
ThrowIfFrozen();
mapValueFormat = value;
}
}
}
public string Name
{
get
{
if (!string.IsNullOrEmpty(name))
{
return name;
}
return originalMember.Name;
}
set
{
SetName(value);
}
}
public bool SupportNull
{
get
{
return HasFlag(16);
}
set
{
SetFlag(16, value, throwIfFrozen: true);
}
}
public ValueMember(RuntimeTypeModel model, Type parentType, int fieldNumber, MemberInfo member, Type memberType, Type itemType, Type defaultType, DataFormat dataFormat, object defaultValue)
: this(model, fieldNumber, memberType, itemType, defaultType, dataFormat)
{
if ((object)parentType == null)
{
throw new ArgumentNullException("parentType");
}
if (fieldNumber < 1 && !Helpers.IsEnum(parentType))
{
throw new ArgumentOutOfRangeException("fieldNumber");
}
originalMember = member ?? throw new ArgumentNullException("member");
this.parentType = parentType;
if (fieldNumber < 1 && !Helpers.IsEnum(parentType))
{
throw new ArgumentOutOfRangeException("fieldNumber");
}
if (defaultValue != null && (object)model.MapType(defaultValue.GetType()) != memberType)
{
defaultValue = ParseDefaultValue(memberType, defaultValue);
}
this.defaultValue = defaultValue;
MetaType metaType = model.FindWithoutAdd(memberType);
if (metaType != null)
{
AsReference = metaType.AsReferenceDefault;
}
else
{
AsReference = MetaType.GetAsReferenceDefault(model, memberType);
}
}
internal ValueMember(RuntimeTypeModel model, int fieldNumber, Type memberType, Type itemType, Type defaultType, DataFormat dataFormat)
{
_fieldNumber = fieldNumber;
this.memberType = memberType ?? throw new ArgumentNullException("memberType");
this.itemType = itemType;
this.defaultType = defaultType;
this.model = model ?? throw new ArgumentNullException("model");
this.dataFormat = dataFormat;
}
internal object GetRawEnumValue()
{
return ((FieldInfo)originalMember).GetRawConstantValue();
}
private static object ParseDefaultValue(Type type, object value)
{
Type underlyingType = Helpers.GetUnderlyingType(type);
if ((object)underlyingType != null)
{
type = underlyingType;
}
if (value is string text)
{
if (Helpers.IsEnum(type))
{
return Helpers.ParseEnum(type, text);
}
switch (Helpers.GetTypeCode(type))
{
case ProtoTypeCode.Boolean:
return bool.Parse(text);
case ProtoTypeCode.Byte:
return byte.Parse(text, NumberStyles.Integer, CultureInfo.InvariantCulture);
case ProtoTypeCode.Char:
if (text.Length == 1)
{
return text[0];
}
throw new FormatException("Single character expected: \"" + text + "\"");
case ProtoTypeCode.DateTime:
return DateTime.Parse(text, CultureInfo.InvariantCulture);
case ProtoTypeCode.Decimal:
return decimal.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.Double:
return double.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.Int16:
return short.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.Int32:
return int.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.Int64:
return long.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.SByte:
return sbyte.Parse(text, NumberStyles.Integer, CultureInfo.InvariantCulture);
case ProtoTypeCode.Single:
return float.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.String:
return text;
case ProtoTypeCode.UInt16:
return ushort.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.UInt32:
return uint.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.UInt64:
return ulong.Parse(text, NumberStyles.Any, CultureInfo.InvariantCulture);
case ProtoTypeCode.TimeSpan:
return TimeSpan.Parse(text);
case ProtoTypeCode.Uri:
return text;
case ProtoTypeCode.Guid:
return new Guid(text);
}
}
if (Helpers.IsEnum(type))
{
return Enum.ToObject(type, value);
}
return Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
public void SetSpecified(MethodInfo getSpecified, MethodInfo setSpecified)
{
if ((object)this.getSpecified != getSpecified || (object)this.setSpecified != setSpecified)
{
if ((object)getSpecified != null && ((object)getSpecified.ReturnType != model.MapType(typeof(bool)) || getSpecified.IsStatic || getSpecified.GetParameters().Length != 0))
{
throw new ArgumentException("Invalid pattern for checking member-specified", "getSpecified");
}
ParameterInfo[] parameters;
if ((object)setSpecified != null && ((object)setSpecified.ReturnType != model.MapType(typeof(void)) || setSpecified.IsStatic || (parameters = setSpecified.GetParameters()).Length != 1 || (object)parameters[0].ParameterType != model.MapType(typeof(bool))))
{
throw new ArgumentException("Invalid pattern for setting member-specified", "setSpecified");
}
ThrowIfFrozen();
this.getSpecified = getSpecified;
this.setSpecified = setSpecified;
}
}
private void ThrowIfFrozen()
{
if (serializer != null)
{
throw new InvalidOperationException("The type cannot be changed once a serializer has been generated");
}
}
internal bool ResolveMapTypes(out Type dictionaryType, out Type keyType, out Type valueType)
{
dictionaryType = (keyType = (valueType = null));
try
{
Type type = memberType;
if (ImmutableCollectionDecorator.IdentifyImmutable(model, MemberType, out var _, out var _, out var _, out var _, out var _, out var _))
{
return false;
}
if (type.IsInterface && type.IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(IDictionary<, >))
{
Type[] genericArguments = memberType.GetGenericArguments();
if (IsValidMapKeyType(genericArguments[0]))
{
keyType = genericArguments[0];
valueType = genericArguments[1];
dictionaryType = memberType;
}
return false;
}
Type[] interfaces = memberType.GetInterfaces();
foreach (Type type2 in interfaces)
{
type = type2;
if (type.IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(IDictionary<, >))
{
if ((object)dictionaryType != null)
{
throw new InvalidOperationException("Multiple dictionary interfaces implemented by type: " + memberType.FullName);
}
Type[] genericArguments2 = type2.GetGenericArguments();
if (IsValidMapKeyType(genericArguments2[0]))
{
keyType = genericArguments2[0];
valueType = genericArguments2[1];
dictionaryType = memberType;
}
}
}
if ((object)dictionaryType == null)
{
return false;
}
Type type3 = null;
Type type4 = null;
model.ResolveListTypes(valueType, ref type3, ref type4);
if ((object)type3 != null)
{
return false;
}
return (object)dictionaryType != null;
}
catch
{
return false;
}
}
private static bool IsValidMapKeyType(Type type)
{
if ((object)type == null || Helpers.IsEnum(type))
{
return false;
}
ProtoTypeCode typeCode = Helpers.GetTypeCode(type);
if ((uint)(typeCode - 3) <= 9u || typeCode == ProtoTypeCode.String)
{
return true;
}
return false;
}
private IProtoSerializer BuildSerializer()
{
int opaqueToken = 0;
try
{
model.TakeLock(ref opaqueToken);
MemberInfo memberInfo = backingMember ?? originalMember;
IProtoSerializer protoSerializer3;
if (IsMap)
{
ResolveMapTypes(out var dictionaryType, out var keyType, out var valueType);
if ((object)dictionaryType == null)
{
throw new InvalidOperationException("Unable to resolve map type for type: " + memberType.FullName);
}
Type type = defaultType;
if ((object)type == null && Helpers.IsClass(memberType))
{
type = memberType;
}
WireType defaultWireType;
IProtoSerializer protoSerializer = TryGetCoreSerializer(model, MapKeyFormat, keyType, out defaultWireType, asReference: false, dynamicType: false, overwriteList: false, allowComplexTypes: false);
if (!AsReference)
{
AsReference = MetaType.GetAsReferenceDefault(model, valueType);
}
WireType defaultWireType2;
IProtoSerializer protoSerializer2 = TryGetCoreSerializer(model, MapValueFormat, valueType, out defaultWireType2, AsReference, DynamicType, overwriteList: false, allowComplexTypes: true);
ConstructorInfo[] constructors = typeof(MapDecorator<, , >).MakeGenericType(dictionaryType, keyType, valueType).GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (constructors.Length != 1)
{
throw new InvalidOperationException("Unable to resolve MapDecorator constructor");
}
protoSerializer3 = (IProtoSerializer)constructors[0].Invoke(new object[9]
{
model,
type,
protoSerializer,
protoSerializer2,
_fieldNumber,
(DataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String,
defaultWireType,
defaultWireType2,
OverwriteList
});
}
else
{
Type type2 = itemType ?? memberType;
protoSerializer3 = TryGetCoreSerializer(model, dataFormat, type2, out var defaultWireType3, AsReference, DynamicType, OverwriteList, allowComplexTypes: true);
if (protoSerializer3 == null)
{
throw new InvalidOperationException("No serializer defined for type: " + type2.FullName);
}
if ((object)itemType != null && SupportNull)
{
if (IsPacked)
{
throw new NotSupportedException("Packed encodings cannot support null values");
}
protoSerializer3 = new TagDecorator(1, defaultWireType3, IsStrict, protoSerializer3);
protoSerializer3 = new NullDecorator(model, protoSerializer3);
protoSerializer3 = new TagDecorator(_fieldNumber, WireType.StartGroup, strict: false, protoSerializer3);
}
else
{
protoSerializer3 = new TagDecorator(_fieldNumber, defaultWireType3, IsStrict, protoSerializer3);
}
if ((object)itemType != null)
{
Type type3 = (SupportNull ? itemType : (Helpers.GetUnderlyingType(itemType) ?? itemType));
protoSerializer3 = ((!memberType.IsArray) ? ((ProtoDecoratorBase)ListDecorator.Create(model, memberType, defaultType, protoSerializer3, _fieldNumber, IsPacked, defaultWireType3, (object)memberInfo != null && PropertyDecorator.CanWrite(model, memberInfo), OverwriteList, SupportNull)) : ((ProtoDecoratorBase)new ArrayDecorator(model, protoSerializer3, _fieldNumber, IsPacked, defaultWireType3, memberType, OverwriteList, SupportNull)));
}
else if (defaultValue != null && !IsRequired && (object)getSpecified == null)
{
protoSerializer3 = new DefaultValueDecorator(model, defaultValue, protoSerializer3);
}
if ((object)memberType == model.MapType(typeof(Uri)))
{
protoSerializer3 = new UriDecorator(model, protoSerializer3);
}
}
if ((object)memberInfo != null)
{
if (memberInfo is PropertyInfo property)
{
protoSerializer3 = new PropertyDecorator(model, parentType, property, protoSerializer3);
}
else
{
if (!(memberInfo is FieldInfo field))
{
throw new InvalidOperationException();
}
protoSerializer3 = new FieldDecorator(parentType, field, protoSerializer3);
}
if ((object)getSpecified != null || (object)setSpecified != null)
{
protoSerializer3 = new MemberSpecifiedDecorator(getSpecified, setSpecified, protoSerializer3);
}
}
return protoSerializer3;
}
finally
{
model.ReleaseLock(opaqueToken);
}
}
private static WireType GetIntWireType(DataFormat format, int width)
{
switch (format)
{
case DataFormat.ZigZag:
return WireType.SignedVariant;
case DataFormat.FixedSize:
if (width != 32)
{
return WireType.Fixed64;
}
return WireType.Fixed32;
case DataFormat.Default:
case DataFormat.TwosComplement:
return WireType.Variant;
default:
throw new InvalidOperationException();
}
}
private static WireType GetDateTimeWireType(DataFormat format)
{
switch (format)
{
case DataFormat.Group:
return WireType.StartGroup;
case DataFormat.FixedSize:
return WireType.Fixed64;
case DataFormat.Default:
case DataFormat.WellKnown:
return WireType.String;
default:
throw new InvalidOperationException();
}
}
internal static IProtoSerializer TryGetCoreSerializer(RuntimeTypeModel model, DataFormat dataFormat, Type type, out WireType defaultWireType, bool asReference, bool dynamicType, bool overwriteList, bool allowComplexTypes)
{
Type underlyingType = Helpers.GetUnderlyingType(type);
if ((object)underlyingType != null)
{
type = underlyingType;
}
if (Helpers.IsEnum(type))
{
if (allowComplexTypes && model != null)
{
defaultWireType = WireType.Variant;
return new EnumSerializer(type, model.GetEnumMap(type));
}
defaultWireType = WireType.None;
return null;
}
switch (Helpers.GetTypeCode(type))
{
case ProtoTypeCode.Int32:
defaultWireType = GetIntWireType(dataFormat, 32);
return new Int32Serializer(model);
case ProtoTypeCode.UInt32:
defaultWireType = GetIntWireType(dataFormat, 32);
return new UInt32Serializer(model);
case ProtoTypeCode.Int64:
defaultWireType = GetIntWireType(dataFormat, 64);
return new Int64Serializer(model);
case ProtoTypeCode.UInt64:
defaultWireType = GetIntWireType(dataFormat, 64);
return new UInt64Serializer(model);
case ProtoTypeCode.String:
defaultWireType = WireType.String;
if (asReference)
{
return new NetObjectSerializer(model, model.MapType(typeof(string)), 0, BclHelpers.NetObjectOptions.AsReference);
}
return new StringSerializer(model);
case ProtoTypeCode.Single:
defaultWireType = WireType.Fixed32;
return new SingleSerializer(model);
case ProtoTypeCode.Double:
defaultWireType = WireType.Fixed64;
return new DoubleSerializer(model);
case ProtoTypeCode.Boolean:
defaultWireType = WireType.Variant;
return new BooleanSerializer(model);
case ProtoTypeCode.DateTime:
defaultWireType = GetDateTimeWireType(dataFormat);
return new DateTimeSerializer(dataFormat, model);
case ProtoTypeCode.Decimal:
defaultWireType = WireType.String;
return new DecimalSerializer(model);
case ProtoTypeCode.Byte:
defaultWireType = GetIntWireType(dataFormat, 32);
return new ByteSerializer(model);
case ProtoTypeCode.SByte:
defaultWireType = GetIntWireType(dataFormat, 32);
return new SByteSerializer(model);
case ProtoTypeCode.Char:
defaultWireType = WireType.Variant;
return new CharSerializer(model);
case ProtoTypeCode.Int16:
defaultWireType = GetIntWireType(dataFormat, 32);
return new Int16Serializer(model);
case ProtoTypeCode.UInt16:
defaultWireType = GetIntWireType(dataFormat, 32);
return new UInt16Serializer(model);
case ProtoTypeCode.TimeSpan:
defaultWireType = GetDateTimeWireType(dataFormat);
return new TimeSpanSerializer(dataFormat, model);
case ProtoTypeCode.Guid:
defaultWireType = ((dataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String);
return new GuidSerializer(model);
case ProtoTypeCode.Uri:
defaultWireType = WireType.String;
return new StringSerializer(model);
case ProtoTypeCode.ByteArray:
defaultWireType = WireType.String;
return new BlobSerializer(model, overwriteList);
case ProtoTypeCode.Type:
defaultWireType = WireType.String;
return new SystemTypeSerializer(model);
default:
{
IProtoSerializer protoSerializer = (model.AllowParseableTypes ? ParseableSerializer.TryCreate(type, model) : null);
if (protoSerializer != null)
{
defaultWireType = WireType.String;
return protoSerializer;
}
if (allowComplexTypes && model != null)
{
int key = model.GetKey(type, demand: false, getBaseKey: true);
MetaType metaType = null;
if (key >= 0)
{
metaType = model[type];
if (dataFormat == DataFormat.Default && metaType.IsGroup)
{
dataFormat = DataFormat.Group;
}
}
if (asReference || dynamicType)
{
BclHelpers.NetObjectOptions netObjectOptions = BclHelpers.NetObjectOptions.None;
if (asReference)
{
netObjectOptions |= BclHelpers.NetObjectOptions.AsReference;
}
if (dynamicType)
{
netObjectOptions |= BclHelpers.NetObjectOptions.DynamicType;
}
if (metaType != null)
{
if (asReference && Helpers.IsValueType(type))
{
string text = "AsReference cannot be used with value-types";
text = ((!(type.Name == "KeyValuePair`2")) ? (text + ": " + type.FullName) : (text + "; please see https://stackoverflow.com/q/14436606/23354"));
throw new InvalidOperationException(text);
}
if (asReference && metaType.IsAutoTuple)
{
netObjectOptions |= BclHelpers.NetObjectOptions.LateSet;
}
if (metaType.UseConstructor)
{
netObjectOptions |= BclHelpers.NetObjectOptions.UseConstructor;
}
}
defaultWireType = ((dataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String);
return new NetObjectSerializer(model, type, key, netObjectOptions);
}
if (key >= 0)
{
defaultWireType = ((dataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String);
return new SubItemSerializer(type, key, metaType, recursionCheck: true);
}
}
defaultWireType = WireType.None;
return null;
}
}
}
internal void SetName(string name)
{
if (name != this.name)
{
ThrowIfFrozen();
this.name = name;
}
}
private bool HasFlag(byte flag)
{
return (flags & flag) == flag;
}
private void SetFlag(byte flag, bool value, bool throwIfFrozen)
{
if (throwIfFrozen && HasFlag(flag) != value)
{
ThrowIfFrozen();
}
if (value)
{
flags |= flag;
}
else
{
flags = (byte)(flags & ~flag);
}
}
internal string GetSchemaTypeName(bool applyNetObjectProxy, ref RuntimeTypeModel.CommonImports imports)
{
Type type = ItemType;
if ((object)type == null)
{
type = MemberType;
}
return model.GetSchemaTypeName(type, DataFormat, applyNetObjectProxy && AsReference, applyNetObjectProxy && DynamicType, ref imports);
}
}