public void SignatureTypeEncoder_SZArray() { var b = new BlobBuilder(); var e = new SignatureTypeEncoder(b); var a = e.SZArray(); AssertEx.Equal(new byte[] { 0x1D }, b.ToArray()); Assert.Same(b, a.Builder); }
private void EncodeTypeSignature(SignatureTypeEncoder encoder, TypeDesc type) { if (type is RuntimeDeterminedType) { EncodeTypeSignature(encoder, ((RuntimeDeterminedType)type).RuntimeDeterminedDetailsType); return; } switch (type.Category) { case TypeFlags.Boolean: encoder.Boolean(); break; case TypeFlags.Byte: encoder.Byte(); break; case TypeFlags.SByte: encoder.SByte(); break; case TypeFlags.Char: encoder.Char(); break; case TypeFlags.Int16: encoder.Int16(); break; case TypeFlags.UInt16: encoder.UInt16(); break; case TypeFlags.Int32: encoder.Int32(); break; case TypeFlags.UInt32: encoder.UInt32(); break; case TypeFlags.Int64: encoder.Int64(); break; case TypeFlags.UInt64: encoder.UInt64(); break; case TypeFlags.Single: encoder.Single(); break; case TypeFlags.Double: encoder.Double(); break; case TypeFlags.IntPtr: encoder.IntPtr(); break; case TypeFlags.UIntPtr: encoder.UIntPtr(); break; case TypeFlags.Void: encoder.Builder.WriteByte((byte)PrimitiveTypeCode.Void); break; case TypeFlags.SignatureTypeVariable: encoder.GenericTypeParameter(((SignatureVariable)type).Index); break; case TypeFlags.SignatureMethodVariable: encoder.GenericMethodTypeParameter(((SignatureMethodVariable)type).Index); break; case TypeFlags.GenericParameter: { var genericTypeDesc = (GenericParameterDesc)type; if (genericTypeDesc.Kind == GenericParameterKind.Type) { encoder.GenericTypeParameter(genericTypeDesc.Index); } else { encoder.GenericMethodTypeParameter(genericTypeDesc.Index); } } break; case TypeFlags.FunctionPointer: { FunctionPointerType fptrType = (FunctionPointerType)type; encoder.FunctionPointer( SignatureCallingConvention.Default, fptrType.Signature.IsStatic ? default(FunctionPointerAttributes) : FunctionPointerAttributes.HasThis, fptrType.Signature.GenericParameterCount); // Return Type Sig EncodeTypeSignature(encoder, fptrType.Signature.ReturnType); // Parameter Types Sig for (int i = 0; i < fptrType.Signature.Length; i++) { EncodeTypeSignature(encoder, fptrType.Signature[i]); } } break; case TypeFlags.Array: { // Skip bounds and lobounds (TODO) ImmutableArray <int> bounds = ImmutableArray.Create <int>(); ImmutableArray <int> lowerBounds = ImmutableArray.Create <int>(); encoder.Array( elementType => EncodeTypeSignature(elementType, ((ArrayType)type).ElementType), arrayShape => arrayShape.Shape(((ArrayType)type).Rank, bounds, lowerBounds)); } break; case TypeFlags.SzArray: encoder.SZArray(); EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType); break; case TypeFlags.ByRef: encoder.Builder.WriteByte((byte)SignatureTypeCode.ByReference); EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType); break; case TypeFlags.Pointer: encoder.Builder.WriteByte((byte)SignatureTypeCode.Pointer); EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType); break; case TypeFlags.Enum: case TypeFlags.Class: case TypeFlags.ValueType: case TypeFlags.Interface: case TypeFlags.Nullable: { if (type == _typeSystemContext.GetWellKnownType(WellKnownType.TypedReference)) { encoder.Builder.WriteByte((byte)PrimitiveTypeCode.TypedReference); } else if (type == _typeSystemContext.GetWellKnownType(WellKnownType.Object)) { encoder.PrimitiveType(PrimitiveTypeCode.Object); } else if (type == _typeSystemContext.GetWellKnownType(WellKnownType.String)) { encoder.PrimitiveType(PrimitiveTypeCode.String); } else if (type.HasInstantiation && !type.IsGenericDefinition) { encoder.GenericInstantiation(MakeTypeRefOrSpecHandle(type.GetTypeDefinition()), type.Instantiation.Length, type.IsValueType); for (int i = 0; i < type.Instantiation.Length; i++) { EncodeTypeSignature(encoder, type.Instantiation[i]); } } else { encoder.Type(MakeTypeRefHandle(type), type.IsValueType); } } break; default: throw new InvalidOperationException("Attempting to encode an invalid type signature."); } }
internal static void FromSystemType(this SignatureTypeEncoder typeEncoder, Type type, IAssemblyMetadata metadata) { if (type.IsByRef) { throw new ArgumentException("ByRef types should be handled by parameter encoder or return type encoder"); } else if (type.IsPointer) { typeEncoder.Pointer().FromSystemType(type.GetElementType(), metadata); } else if (type.IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type)); } else if (type == typeof(string)) { typeEncoder.String(); } else if (type == typeof(object)) { typeEncoder.Object(); } else if (type == typeof(void)) { throw new ArgumentException( "Void type is not allowed in SignatureTypeEncoder. Please, use FromSystemType from ReturnTypeEncoder.", nameof(type)); } else if (type.IsArray) { var elementType = type.GetElementType(); if (type.GetArrayRank() == 1) { typeEncoder.SZArray().FromSystemType(elementType, metadata); } else { typeEncoder.Array( x => x.FromSystemType(elementType, metadata), x => x.Shape( type.GetArrayRank(), ImmutableArray.Create <int>(), ImmutableArray.CreateRange <int>(Enumerable.Repeat(0, type.GetArrayRank())) // better matches metadata from C# )); } } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); var typeHandler = metadata.GetTypeHandle(genericTypeDef); var genericArguments = type.GetGenericArguments(); var inst = typeEncoder.GenericInstantiation(typeHandler, genericArguments.Length, type.IsValueType); foreach (var ga in genericArguments) { if (ga.IsGenericParameter) { inst.AddArgument().GenericTypeParameter(ga.GenericParameterPosition); } else { inst.AddArgument().FromSystemType(ga, metadata); } } } else if (type.IsGenericMethodParameter()) { typeEncoder.GenericMethodTypeParameter(type.GenericParameterPosition); } else if (type.IsGenericParameter) { typeEncoder.GenericTypeParameter(type.GenericParameterPosition); } else { var typeHandler = metadata.GetTypeHandle(type); typeEncoder.Type(typeHandler, type.IsValueType); } }
public void SignatureTypeEncoder_SZArray() { var b = new BlobBuilder(); var e = new SignatureTypeEncoder(b); Assert.Same(b, e.Builder); var a = e.SZArray(); AssertEx.Equal(new byte[] { 0x1D }, b.ToArray()); Assert.Same(b, a.Builder); }