public void SignatureTypeEncoder_FunctionPointer() { var b = new BlobBuilder(); var e = new SignatureTypeEncoder(b); Assert.Same(b, e.Builder); var m = e.FunctionPointer( SignatureCallingConvention.CDecl, FunctionPointerAttributes.HasThis, genericParameterCount: 1); Assert.Same(b, m.Builder); AssertEx.Equal(new byte[] { 0x1B, 0x21, 0x01 }, b.ToArray()); b.Clear(); e.FunctionPointer( SignatureCallingConvention.Default, FunctionPointerAttributes.HasExplicitThis, genericParameterCount: 0); AssertEx.Equal(new byte[] { 0x1B, 0x60 }, b.ToArray()); b.Clear(); e.FunctionPointer(); AssertEx.Equal(new byte[] { 0x1B, 0x00 }, b.ToArray()); b.Clear(); AssertExtensions.Throws <ArgumentException>("attributes", () => e.FunctionPointer(0, (FunctionPointerAttributes)1000, genericParameterCount: 0)); Assert.Throws <ArgumentOutOfRangeException>(() => e.FunctionPointer(0, 0, genericParameterCount: -1)); Assert.Throws <ArgumentOutOfRangeException>(() => e.FunctionPointer(0, 0, genericParameterCount: ushort.MaxValue + 1)); Assert.Equal(0, b.Count); }
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."); } }
public void SignatureTypeEncoder_FunctionPointer() { var b = new BlobBuilder(); var e = new SignatureTypeEncoder(b); Assert.Same(b, e.Builder); var m = e.FunctionPointer( SignatureCallingConvention.CDecl, FunctionPointerAttributes.HasThis, genericParameterCount: 1); Assert.Same(b, m.Builder); AssertEx.Equal(new byte[] { 0x1B, 0x21, 0x01 }, b.ToArray()); b.Clear(); e.FunctionPointer( SignatureCallingConvention.Default, FunctionPointerAttributes.HasExplicitThis, genericParameterCount: 0); AssertEx.Equal(new byte[] { 0x1B, 0x60 }, b.ToArray()); b.Clear(); e.FunctionPointer(); AssertEx.Equal(new byte[] { 0x1B, 0x00 }, b.ToArray()); b.Clear(); Assert.Throws<ArgumentException>(() => e.FunctionPointer(0, (FunctionPointerAttributes)1000, genericParameterCount: 0)); Assert.Throws<ArgumentOutOfRangeException>(() => e.FunctionPointer(0, 0, genericParameterCount: -1)); Assert.Throws<ArgumentOutOfRangeException>(() => e.FunctionPointer(0, 0, genericParameterCount: ushort.MaxValue + 1)); Assert.Equal(0, b.Count); }