private ImmutableArray <CustomAttributeNamedArgument <TType> > DecodeNamedArguments(ref BlobReader valueReader) { int count = valueReader.ReadUInt16(); if (count == 0) { return(ImmutableArray <CustomAttributeNamedArgument <TType> > .Empty); } var arguments = ImmutableArray.CreateBuilder <CustomAttributeNamedArgument <TType> >(count); for (int i = 0; i < count; i++) { CustomAttributeNamedArgumentKind kind = (CustomAttributeNamedArgumentKind)valueReader.ReadSerializationTypeCode(); if (kind != CustomAttributeNamedArgumentKind.Field && kind != CustomAttributeNamedArgumentKind.Property) { throw new BadImageFormatException(); } ArgumentTypeInfo info = DecodeNamedArgumentType(ref valueReader); string? name = valueReader.ReadSerializedString(); CustomAttributeTypedArgument <TType> argument = DecodeArgument(ref valueReader, info); arguments.Add(new CustomAttributeNamedArgument <TType>(name, kind, argument.Type, argument.Value)); } return(arguments.MoveToImmutable()); }
private ImmutableArray <CustomAttributeTypedArgument <TType> >?DecodeArrayArgument(ref BlobReader blobReader, ArgumentTypeInfo info) { int count = blobReader.ReadInt32(); if (count == -1) { return(null); } if (count == 0) { return(ImmutableArray <CustomAttributeTypedArgument <TType> > .Empty); } if (count < 0) { throw new BadImageFormatException(); } var elementInfo = new ArgumentTypeInfo { Type = info.ElementType, TypeCode = info.ElementTypeCode, }; var array = ImmutableArray.CreateBuilder <CustomAttributeTypedArgument <TType> >(count); for (int i = 0; i < count; i++) { array.Add(DecodeArgument(ref blobReader, elementInfo)); } return(array.MoveToImmutable()); }
private ArgumentTypeInfo DecodeNamedArgumentType(ref BlobReader valueReader, bool isElementType = false) { var info = new ArgumentTypeInfo { TypeCode = valueReader.ReadSerializationTypeCode(), }; switch (info.TypeCode) { case SerializationTypeCode.Boolean: case SerializationTypeCode.Byte: case SerializationTypeCode.Char: case SerializationTypeCode.Double: case SerializationTypeCode.Int16: case SerializationTypeCode.Int32: case SerializationTypeCode.Int64: case SerializationTypeCode.SByte: case SerializationTypeCode.Single: case SerializationTypeCode.String: case SerializationTypeCode.UInt16: case SerializationTypeCode.UInt32: case SerializationTypeCode.UInt64: info.Type = _provider.GetPrimitiveType((PrimitiveTypeCode)info.TypeCode); break; case SerializationTypeCode.Type: info.Type = _provider.GetSystemType(); break; case SerializationTypeCode.TaggedObject: info.Type = _provider.GetPrimitiveType(PrimitiveTypeCode.Object); break; case SerializationTypeCode.SZArray: if (isElementType) { // jagged arrays are not allowed. throw new BadImageFormatException(); } var elementInfo = DecodeNamedArgumentType(ref valueReader, isElementType: true); info.ElementType = elementInfo.Type; info.ElementTypeCode = elementInfo.TypeCode; info.Type = _provider.GetSZArrayType(info.ElementType); break; case SerializationTypeCode.Enum: string?typeName = valueReader.ReadSerializedString(); info.Type = _provider.GetTypeFromSerializedName(typeName !); info.TypeCode = (SerializationTypeCode)_provider.GetUnderlyingEnumType(info.Type); break; default: throw new BadImageFormatException(); } return(info); }
// Decodes a fixed argument type of a custom attribute from its constructor signature. // // Note that we do not decode the full constructor signature using DecodeMethodSignature // but instead decode one parameter at a time as we read the value blob. This is both // better perf-wise, but even more important is that we can't actually reason about // a method signature with opaque TType values without adding some unnecessary chatter // with the provider. private ArgumentTypeInfo DecodeFixedArgumentType(ref BlobReader signatureReader, bool isElementType = false) { SignatureTypeCode signatureTypeCode = signatureReader.ReadSignatureTypeCode(); var info = new ArgumentTypeInfo { TypeCode = (SerializationTypeCode)signatureTypeCode, }; switch (signatureTypeCode) { case SignatureTypeCode.Boolean: case SignatureTypeCode.Byte: case SignatureTypeCode.Char: case SignatureTypeCode.Double: case SignatureTypeCode.Int16: case SignatureTypeCode.Int32: case SignatureTypeCode.Int64: case SignatureTypeCode.SByte: case SignatureTypeCode.Single: case SignatureTypeCode.String: case SignatureTypeCode.UInt16: case SignatureTypeCode.UInt32: case SignatureTypeCode.UInt64: info.Type = _provider.GetPrimitiveType((PrimitiveTypeCode)signatureTypeCode); break; case SignatureTypeCode.Object: info.TypeCode = SerializationTypeCode.TaggedObject; info.Type = _provider.GetPrimitiveType(PrimitiveTypeCode.Object); break; case SignatureTypeCode.TypeHandle: // Parameter is type def or ref and is only allowed to be System.Type or Enum. EntityHandle handle = signatureReader.ReadTypeHandle(); info.Type = GetTypeFromHandle(handle); info.TypeCode = _provider.IsSystemType(info.Type) ? SerializationTypeCode.Type : (SerializationTypeCode)_provider.GetUnderlyingEnumType(info.Type); break; case SignatureTypeCode.SZArray: if (isElementType) { // jagged arrays are not allowed. throw new BadImageFormatException(); } var elementInfo = DecodeFixedArgumentType(ref signatureReader, isElementType: true); info.ElementType = elementInfo.Type; info.ElementTypeCode = elementInfo.TypeCode; info.Type = _provider.GetSZArrayType(info.ElementType); break; default: throw new BadImageFormatException(); } return(info); }
private ImmutableArray <CustomAttributeTypedArgument <TType> > DecodeFixedArguments(ref BlobReader signatureReader, ref BlobReader valueReader, int count) { if (count == 0) { return(ImmutableArray <CustomAttributeTypedArgument <TType> > .Empty); } var arguments = ImmutableArray.CreateBuilder <CustomAttributeTypedArgument <TType> >(count); for (int i = 0; i < count; i++) { ArgumentTypeInfo info = DecodeFixedArgumentType(ref signatureReader); arguments.Add(DecodeArgument(ref valueReader, info)); } return(arguments.MoveToImmutable()); }
private CustomAttributeTypedArgument <TType> DecodeArgument(ref BlobReader valueReader, ArgumentTypeInfo info) { if (info.TypeCode == SerializationTypeCode.TaggedObject) { info = DecodeNamedArgumentType(ref valueReader); } // PERF_TODO: https://github.com/dotnet/corefx/issues/6533 // Cache /reuse common arguments to avoid boxing (small integers, true, false). object?value; switch (info.TypeCode) { case SerializationTypeCode.Boolean: value = valueReader.ReadBoolean(); break; case SerializationTypeCode.Byte: value = valueReader.ReadByte(); break; case SerializationTypeCode.Char: value = valueReader.ReadChar(); break; case SerializationTypeCode.Double: value = valueReader.ReadDouble(); break; case SerializationTypeCode.Int16: value = valueReader.ReadInt16(); break; case SerializationTypeCode.Int32: value = valueReader.ReadInt32(); break; case SerializationTypeCode.Int64: value = valueReader.ReadInt64(); break; case SerializationTypeCode.SByte: value = valueReader.ReadSByte(); break; case SerializationTypeCode.Single: value = valueReader.ReadSingle(); break; case SerializationTypeCode.UInt16: value = valueReader.ReadUInt16(); break; case SerializationTypeCode.UInt32: value = valueReader.ReadUInt32(); break; case SerializationTypeCode.UInt64: value = valueReader.ReadUInt64(); break; case SerializationTypeCode.String: value = valueReader.ReadSerializedString(); break; case SerializationTypeCode.Type: string?typeName = valueReader.ReadSerializedString(); value = _provider.GetTypeFromSerializedName(typeName !); break; case SerializationTypeCode.SZArray: value = DecodeArrayArgument(ref valueReader, info); break; default: throw new BadImageFormatException(); } return(new CustomAttributeTypedArgument <TType>(info.Type, value)); }