public override object Read(Type useType, object value, ProtoReader source) { Helpers.DebugAssert(value != null); object newValue = Tail.Read(useType, (Tail.RequiresOldValue ? field.GetValue(value) : null), source); if(newValue != null) field.SetValue(value,newValue); return null; }
public ConversationWrapper(Conversion conv, Operand op, Type @from, Type to) { _conv = conv; _op = op; _to = to; _from = @from; }
public ArrayDecorator(TypeModel model, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, Type arrayType, bool overwriteList, bool supportNull) : base(tail) { Helpers.DebugAssert(arrayType != null, "arrayType should be non-null"); Helpers.DebugAssert(arrayType.IsArray && arrayType.GetArrayRank() == 1, "should be single-dimension array; " + arrayType.FullName); this.itemType = arrayType.GetElementType(); #if NO_GENERICS Type underlyingItemType = itemType; #else Type underlyingItemType = supportNull ? itemType : (Helpers.GetUnderlyingType(itemType) ?? itemType); #endif Helpers.DebugAssert(underlyingItemType == Tail.ExpectedType, "invalid tail"); Helpers.DebugAssert(Tail.ExpectedType != model.MapType(typeof(byte)), "Should have used BlobSerializer"); if ((writePacked || packedWireType != WireType.None) && fieldNumber <= 0) throw new ArgumentOutOfRangeException("fieldNumber"); if (!ListDecorator.CanPack(packedWireType)) { if (writePacked) throw new InvalidOperationException("Only simple data-types can use packed encoding"); packedWireType = WireType.None; } this.fieldNumber = fieldNumber; this.packedWireType = packedWireType; if (writePacked) options |= OPTIONS_WritePacked; if (overwriteList) options |= OPTIONS_OverwriteList; if (supportNull) options |= OPTIONS_SupportNull; this.arrayType = arrayType; }
public static AttributeMap[] Create(TypeModel model, Type type, bool inherit) { #if FEAT_IKVM Type attribType = model.MapType(typeof(System.Attribute)); System.Collections.Generic.IList<CustomAttributeData> all = type.__GetCustomAttributes(attribType, inherit); AttributeMap[] result = new AttributeMap[all.Count]; int index = 0; foreach (CustomAttributeData attrib in all) { result[index++] = new AttributeDataMap(attrib); } return result; #else #if WINRT Attribute[] all = System.Linq.Enumerable.ToArray(type.GetTypeInfo().GetCustomAttributes(inherit)); #else var all = type.GetCustomAttributes(inherit); #endif var result = new AttributeMap[all.Length]; for (var i = 0; i < all.Length; i++) { result[i] = new ReflectionAttributeMap((Attribute) all[i]); } return result; #endif }
public NewDelegate(Type delegateType, Operand target, string methodName, ITypeMapper typeMapper) { _delegateType = delegateType; _target = target; _typeMapper = typeMapper; Initialize(target.GetReturnType(typeMapper), methodName); }
public NetObjectSerializer(TypeModel model, Type type, int key, BclHelpers.NetObjectOptions options) { bool dynamicType = (options & BclHelpers.NetObjectOptions.DynamicType) != 0; this.key = dynamicType ? -1 : key; this.type = dynamicType ? model.MapType(typeof (object)) : type; this.options = options; }
public SafeCast(Operand op, Type t) { _op = op; _t = t; if (t.IsValueType) _conditional = _op.Is(_t).Conditional(_op.Cast(_t), new DefaultValue(_t)); }
public override void Write(Type useType, object value, ProtoWriter dest) { if(getSpecified == null || (bool)getSpecified.Invoke(value, null)) { Tail.Write(useType, value, dest); } }
internal static FieldInfo GetClassLiteralField(Type type) { Debug.Assert(type != Types.Void); if (classLiteralType == null) { #if STATIC_COMPILER classLiteralType = JVM.CoreAssembly.GetType("ikvm.internal.ClassLiteral`1"); #elif !FIRST_PASS classLiteralType = typeof([email protected]<>); #endif } #if !STATIC_COMPILER if (!IsTypeBuilder(type)) { return classLiteralType.MakeGenericType(type).GetField("Value", BindingFlags.Public | BindingFlags.Static); } #endif if (classLiteralField == null) { classLiteralField = classLiteralType.GetField("Value", BindingFlags.Public | BindingFlags.Static); } #if !NOEMIT return TypeBuilder.GetField(classLiteralType.MakeGenericType(type), classLiteralField); #else return null; #endif }
private void EmitBeq(Compiler.CompilerContext ctx, Compiler.CodeLabel label, Type type) { switch (Helpers.GetTypeCode(type)) { case ProtoTypeCode.Boolean: case ProtoTypeCode.Byte: case ProtoTypeCode.Char: case ProtoTypeCode.Double: case ProtoTypeCode.Int16: case ProtoTypeCode.Int32: case ProtoTypeCode.Int64: case ProtoTypeCode.SByte: case ProtoTypeCode.Single: case ProtoTypeCode.UInt16: case ProtoTypeCode.UInt32: case ProtoTypeCode.UInt64: ctx.BranchIfEqual(label, false); break; default: MethodInfo method = type.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.Static, null, new Type[] { type, type}, null); if (method == null || method.ReturnType != ctx.MapType(typeof(bool))) { throw new InvalidOperationException("No suitable equality operator found for default-values of type: " + type.FullName); } ctx.EmitCall(method); ctx.BranchIfTrue(label, false); break; } }
public FieldDecorator(Type forType, FieldInfo field, IProtoSerializer tail) : base(tail) { Helpers.DebugAssert(forType != null); Helpers.DebugAssert(field != null); this.forType = forType; this.field = field; }
static Type ResolveIReadOnlyCollection(Type declaredType, Type t) { #if WINRT foreach (Type intImplBasic in declaredType.GetTypeInfo().ImplementedInterfaces) { TypeInfo intImpl = intImplBasic.GetTypeInfo(); if (intImpl.IsGenericType && intImpl.Name.StartsWith("IReadOnlyCollection`")) { if(t != null) { Type[] typeArgs = intImpl.GenericTypeArguments; if (typeArgs.Length != 1 && typeArgs[0] != t) continue; } return intImplBasic; } } #else foreach (Type intImpl in declaredType.GetInterfaces()) { if (intImpl.IsGenericType && intImpl.Name.StartsWith("IReadOnlyCollection`")) { if(t != null) { Type[] typeArgs = intImpl.GetGenericArguments(); if (typeArgs.Length != 1 && typeArgs[0] != t) continue; } return intImpl; } } #endif return null; }
public override object Read(Type useType, object value, ProtoReader source) { Helpers.DebugAssert(fieldNumber == source.FieldNumber); if (strict) { source.Assert(wireType); } else if (NeedsHint) { source.Hint(wireType); } return Tail.Read(useType,value, source); }
internal EventGen(TypeGen owner, string name, Type type, MethodAttributes mthAttr) { _owner = owner; Name = name; _type = type; _attrs = mthAttr; }
private static bool HasCast(Type type, Type from, Type to, out MethodInfo op) { #if WINRT System.Collections.Generic.List<MethodInfo> list = new System.Collections.Generic.List<MethodInfo>(); foreach (var item in type.GetRuntimeMethods()) { if (item.IsStatic) list.Add(item); } MethodInfo[] found = list.ToArray(); #else const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo[] found = type.GetMethods(flags); #endif for(int i = 0 ; i < found.Length ; i++) { MethodInfo m = found[i]; if ((m.Name != "op_Implicit" && m.Name != "op_Explicit") || m.ReturnType != to) { continue; } ParameterInfo[] paramTypes = m.GetParameters(); if(paramTypes.Length == 1 && paramTypes[0].ParameterType == from) { op = m; return true; } } op = null; return false; }
internal static bool IsReflectionOnly(Type type) { while (type.HasElementType) { type = type.GetElementType(); } Assembly asm = type.Assembly; if (asm != null && asm.ReflectionOnly) { return true; } if (!type.IsGenericType || type.IsGenericTypeDefinition) { return false; } // we have a generic type instantiation, it might have ReflectionOnly type arguments foreach (Type arg in type.GetGenericArguments()) { if (IsReflectionOnly(arg)) { return true; } } return false; }
public override void Write(Type useType, object value, ProtoWriter dest) { if (!object.Equals(value, defaultValue)) { Tail.Write(useType, value, dest); } }
public static ParseableSerializer TryCreate(Type type, TypeModel model) { if (type == null) throw new ArgumentNullException("type"); #if WINRT || PORTABLE || COREFX MethodInfo method = null; #if WINRT || COREFX foreach (MethodInfo tmp in type.GetTypeInfo().GetDeclaredMethods("Parse")) #else foreach (MethodInfo tmp in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)) #endif { ParameterInfo[] p; if (tmp.Name == "Parse" && tmp.IsPublic && tmp.IsStatic && tmp.DeclaringType == type && (p = tmp.GetParameters()) != null && p.Length == 1 && p[0].ParameterType == typeof(string)) { method = tmp; break; } } #else MethodInfo method = type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new Type[] { model.MapType(typeof(string)) }, null); #endif if (method != null && method.ReturnType == type) { if (Helpers.IsValueType(type)) { MethodInfo toString = GetCustomToString(type); if (toString == null || toString.ReturnType != model.MapType(typeof(string))) return null; // need custom ToString, fools } return new ParseableSerializer(method); } return null; }
internal PropertyGen(TypeGen owner, MethodAttributes attrs, Type type, string name) { _owner = owner; _attrs = attrs; _type = type; Name = name; _indexParameters = new ParameterGenCollection(owner.TypeMapper); }
public EnumPair(int wireValue, object raw, Type type) { WireValue = wireValue; RawValue = raw; #if !FEAT_IKVM TypedValue = (Enum)Enum.ToObject(type, raw); #endif }
internal static bool CanOwnDynamicMethod(Type type) { return type != null && !type.IsInterface && !type.HasElementType && !type.IsGenericTypeDefinition && !type.IsGenericParameter; }
/// <summary> /// 是否是空标签 /// </summary> public bool IsNoAttribute(Type infoType) { if (TypeIsNoAttribute.ContainsKey(infoType)) { return TypeIsNoAttribute[infoType]; } return false; }
void AppendTypeNameNoOuter(StringBuilder sb, Type type) { if (type.__Namespace != null) { sb.Append(QuoteIdentifier(type.__Namespace)); sb.Append('.'); } sb.Append(QuoteIdentifier(type.__Name)); }
void AppendTypeName(StringBuilder sb, Type type) { if (type.IsNested) { AppendTypeName(sb, type.DeclaringType); sb.Append('/'); } AppendTypeNameNoOuter(sb, type); }
public PropertyDecorator(TypeModel model, Type forType, PropertyInfo property, IProtoSerializer tail) : base(tail) { Helpers.DebugAssert(forType != null); Helpers.DebugAssert(property != null); this.forType = forType; this.property = property; SanityCheck(model, property, tail, out readOptionsWriteValue, true, true); shadowSetter = GetShadowSetter(model, property); }
internal FieldGen(TypeGen owner, string name, Type type, FieldAttributes attrs) { _owner = owner; _attrs = attrs; Name = name; _type = type; _fb = owner.TypeBuilder.DefineField(name, type, attrs); owner.RegisterForCompletion(this); }
private static bool HasCast(TypeModel model, Type type, Type from, Type to, out MethodInfo op) { #if WINRT System.Collections.Generic.List<MethodInfo> list = new System.Collections.Generic.List<MethodInfo>(); foreach (var item in type.GetRuntimeMethods()) { if (item.IsStatic) list.Add(item); } MethodInfo[] found = list.ToArray(); #else const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo[] found = type.GetMethods(flags); #endif ParameterInfo[] paramTypes; Type convertAttributeType = null; for (int i = 0; i < found.Length; i++) { MethodInfo m = found[i]; if (m.ReturnType != to) continue; paramTypes = m.GetParameters(); if(paramTypes.Length == 1 && paramTypes[0].ParameterType == from) { if (convertAttributeType == null) { convertAttributeType = model.MapType(typeof(ProtoConverterAttribute), false); if (convertAttributeType == null) { // attribute isn't defined in the source assembly: stop looking break; } } if (m.IsDefined(convertAttributeType, true)) { op = m; return true; } } } for(int i = 0 ; i < found.Length ; i++) { MethodInfo m = found[i]; if ((m.Name != "op_Implicit" && m.Name != "op_Explicit") || m.ReturnType != to) { continue; } paramTypes = m.GetParameters(); if(paramTypes.Length == 1 && paramTypes[0].ParameterType == from) { op = m; return true; } } op = null; return false; }
private DotNetTypeWrapper(Type type, string name) : base(TypeFlags.None, GetModifiers(type), name) { Debug.Assert(!(type.IsByRef), type.FullName); Debug.Assert(!(type.IsPointer), type.FullName); Debug.Assert(!(type.Name.EndsWith("[]")), type.FullName); Debug.Assert(!(type is TypeBuilder), type.FullName); Debug.Assert(!(AttributeHelper.IsJavaModule(type.Module))); this.type = type; }
static MethodHandleUtil() { #if STATIC_COMPILER typeofMHA = StaticCompiler.GetRuntimeType("IKVM.Runtime.MHA`8"); typeofMHV = new Type[] { StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`1"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`2"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`3"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`4"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`5"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`6"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`7"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`8"), }; typeofMH = new Type[] { null, StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`1"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`2"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`3"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`4"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`5"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`6"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`7"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`8"), StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`9"), }; #else typeofMHA = typeof(IKVM.Runtime.MHA<,,,,,,,>); typeofMHV = new Type[] { typeof(IKVM.Runtime.MHV), typeof(IKVM.Runtime.MHV<>), typeof(IKVM.Runtime.MHV<,>), typeof(IKVM.Runtime.MHV<,,>), typeof(IKVM.Runtime.MHV<,,,>), typeof(IKVM.Runtime.MHV<,,,,>), typeof(IKVM.Runtime.MHV<,,,,,>), typeof(IKVM.Runtime.MHV<,,,,,,>), typeof(IKVM.Runtime.MHV<,,,,,,,>), }; typeofMH = new Type[] { null, typeof(IKVM.Runtime.MH<>), typeof(IKVM.Runtime.MH<,>), typeof(IKVM.Runtime.MH<,,>), typeof(IKVM.Runtime.MH<,,,>), typeof(IKVM.Runtime.MH<,,,,>), typeof(IKVM.Runtime.MH<,,,,,>), typeof(IKVM.Runtime.MH<,,,,,,>), typeof(IKVM.Runtime.MH<,,,,,,,>), typeof(IKVM.Runtime.MH<,,,,,,,,>), }; #endif }
internal static void Create(ModuleBuilder modb, ClassLoaderWrapper loader) { TypeBuilder tb = modb.DefineType(DotNetTypeWrapper.GenericDelegateInterfaceTypeName, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public); tb.DefineGenericParameters("T")[0].SetBaseTypeConstraint(Types.MulticastDelegate); genericDelegateInterfaceType = tb.CreateType(); genericAttributeAnnotationType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationTypeName); genericAttributeAnnotationMultipleType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationMultipleTypeName); genericAttributeAnnotationReturnValueType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationReturnValueTypeName); CreateEnumEnum(modb, loader); }
public static bool Is(this IKVM.Reflection.Type self, string @namespace, string name) { return((self.Namespace == @namespace) && (self.Name == name)); }
public void EmitRead(Compiler.CompilerContext ctx, Compiler.Local incoming) { using (Compiler.Local objValue = ctx.GetLocalWithValue(ExpectedType, incoming)) { Compiler.Local[] locals = new Compiler.Local[members.Length]; try { for (int i = 0; i < locals.Length; i++) { Type type = GetMemberType(i); bool store = true; locals[i] = new Compiler.Local(ctx, type); if (!Helpers.IsValueType(ExpectedType)) { // value-types always read the old value if (Helpers.IsValueType(type)) { switch (Helpers.GetTypeCode(type)) { case ProtoTypeCode.Boolean: case ProtoTypeCode.Byte: case ProtoTypeCode.Int16: case ProtoTypeCode.Int32: case ProtoTypeCode.SByte: case ProtoTypeCode.UInt16: case ProtoTypeCode.UInt32: ctx.LoadValue(0); break; case ProtoTypeCode.Int64: case ProtoTypeCode.UInt64: ctx.LoadValue(0L); break; case ProtoTypeCode.Single: ctx.LoadValue(0.0F); break; case ProtoTypeCode.Double: ctx.LoadValue(0.0D); break; case ProtoTypeCode.Decimal: ctx.LoadValue(0M); break; case ProtoTypeCode.Guid: ctx.LoadValue(Guid.Empty); break; default: ctx.LoadAddress(locals[i], type); ctx.EmitCtor(type); store = false; break; } } else { ctx.LoadNullRef(); } if (store) { ctx.StoreValue(locals[i]); } } } Compiler.CodeLabel skipOld = Helpers.IsValueType(ExpectedType) ? new Compiler.CodeLabel() : ctx.DefineLabel(); if (!Helpers.IsValueType(ExpectedType)) { ctx.LoadAddress(objValue, ExpectedType); ctx.BranchIfFalse(skipOld, false); } for (int i = 0; i < members.Length; i++) { ctx.LoadAddress(objValue, ExpectedType); if (members[i] is FieldInfo) { ctx.LoadValue((FieldInfo)members[i]); } else if (members[i] is PropertyInfo) { ctx.LoadValue((PropertyInfo)members[i]); } ctx.StoreValue(locals[i]); } if (!Helpers.IsValueType(ExpectedType)) { ctx.MarkLabel(skipOld); } using (Compiler.Local fieldNumber = new Compiler.Local(ctx, ctx.MapType(typeof(int)))) { Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel(), notRecognised = ctx.DefineLabel(); ctx.Branch(@continue, false); Compiler.CodeLabel[] handlers = new Compiler.CodeLabel[members.Length]; for (int i = 0; i < members.Length; i++) { handlers[i] = ctx.DefineLabel(); } ctx.MarkLabel(processField); ctx.LoadValue(fieldNumber); ctx.LoadValue(1); ctx.Subtract(); // jump-table is zero-based ctx.Switch(handlers); // and the default: ctx.Branch(notRecognised, false); for (int i = 0; i < handlers.Length; i++) { ctx.MarkLabel(handlers[i]); IProtoSerializer tail = tails[i]; Compiler.Local oldValIfNeeded = tail.RequiresOldValue ? locals[i] : null; ctx.ReadNullCheckedTail(locals[i].Type, tail, oldValIfNeeded); if (tail.ReturnsValue) { if (Helpers.IsValueType(locals[i].Type)) { ctx.StoreValue(locals[i]); } else { Compiler.CodeLabel hasValue = ctx.DefineLabel(), allDone = ctx.DefineLabel(); ctx.CopyValue(); ctx.BranchIfTrue(hasValue, true); // interpret null as "don't assign" ctx.DiscardValue(); ctx.Branch(allDone, true); ctx.MarkLabel(hasValue); ctx.StoreValue(locals[i]); ctx.MarkLabel(allDone); } } ctx.Branch(@continue, false); } ctx.MarkLabel(notRecognised); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); ctx.MarkLabel(@continue); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(fieldNumber); ctx.LoadValue(0); ctx.BranchIfGreater(processField, false); } for (int i = 0; i < locals.Length; i++) { ctx.LoadValue(locals[i]); } ctx.EmitCtor(ctor); ctx.StoreValue(objValue); } finally { for (int i = 0; i < locals.Length; i++) { if (locals[i] != null) { locals[i].Dispose(); // release for re-use } } } } }
protected MethodInfo GetEnumeratorInfo(TypeModel model, out MethodInfo moveNext, out MethodInfo current) { #if WINRT || COREFX TypeInfo enumeratorType = null, iteratorType, expectedType = ExpectedType.GetTypeInfo(); #else Type enumeratorType = null, iteratorType, expectedType = ExpectedType; #endif // try a custom enumerator MethodInfo getEnumerator = Helpers.GetInstanceMethod(expectedType, "GetEnumerator", null); Type itemType = Tail.ExpectedType; Type getReturnType = null; if (getEnumerator != null) { getReturnType = getEnumerator.ReturnType; iteratorType = getReturnType #if WINRT || COREFX || COREFX .GetTypeInfo() #endif ; moveNext = Helpers.GetInstanceMethod(iteratorType, "MoveNext", null); PropertyInfo prop = Helpers.GetProperty(iteratorType, "Current", false); current = prop == null ? null : Helpers.GetGetMethod(prop, false, false); if (moveNext == null && (model.MapType(ienumeratorType).IsAssignableFrom(iteratorType))) { moveNext = Helpers.GetInstanceMethod(model.MapType(ienumeratorType), "MoveNext", null); } // fully typed if (moveNext != null && moveNext.ReturnType == model.MapType(typeof(bool)) && current != null && current.ReturnType == itemType) { return(getEnumerator); } moveNext = current = getEnumerator = null; } #if !NO_GENERICS // try IEnumerable<T> Type tmp = model.MapType(typeof(System.Collections.Generic.IEnumerable <>), false); if (tmp != null) { tmp = tmp.MakeGenericType(itemType); #if WINRT || COREFX enumeratorType = tmp.GetTypeInfo(); #else enumeratorType = tmp; #endif } ; if (enumeratorType != null && enumeratorType.IsAssignableFrom(expectedType)) { getEnumerator = Helpers.GetInstanceMethod(enumeratorType, "GetEnumerator"); getReturnType = getEnumerator.ReturnType; #if WINRT || COREFX iteratorType = getReturnType.GetTypeInfo(); #else iteratorType = getReturnType; #endif moveNext = Helpers.GetInstanceMethod(model.MapType(ienumeratorType), "MoveNext"); current = Helpers.GetGetMethod(Helpers.GetProperty(iteratorType, "Current", false), false, false); return(getEnumerator); } #endif // give up and fall-back to non-generic IEnumerable enumeratorType = model.MapType(ienumerableType); getEnumerator = Helpers.GetInstanceMethod(enumeratorType, "GetEnumerator"); getReturnType = getEnumerator.ReturnType; iteratorType = getReturnType #if WINRT || COREFX .GetTypeInfo() #endif ; moveNext = Helpers.GetInstanceMethod(iteratorType, "MoveNext"); current = Helpers.GetGetMethod(Helpers.GetProperty(iteratorType, "Current", false), false, false); return(getEnumerator); }
protected override void EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { using (Compiler.Local oldList = AppendToCollection ? ctx.GetLocalWithValue(ExpectedType, valueFrom) : null) using (Compiler.Local builder = new Compiler.Local(ctx, builderFactory.ReturnType)) { ctx.EmitCall(builderFactory); ctx.StoreValue(builder); if (AppendToCollection) { Compiler.CodeLabel done = ctx.DefineLabel(); if (!ExpectedType.IsValueType) { ctx.LoadValue(oldList); ctx.BranchIfFalse(done, false); // old value null; nothing to add } PropertyInfo prop = Helpers.GetProperty(ExpectedType, "Length", false); if (prop == null) { prop = Helpers.GetProperty(ExpectedType, "Count", false); } #if !NO_GENERICS if (prop == null) { prop = Helpers.GetProperty(ResolveIReadOnlyCollection(ExpectedType, Tail.ExpectedType), "Count", false); } #endif ctx.LoadAddress(oldList, oldList.Type); ctx.EmitCall(Helpers.GetGetMethod(prop, false, false)); ctx.BranchIfFalse(done, false); // old list is empty; nothing to add Type voidType = ctx.MapType(typeof(void)); if (addRange != null) { ctx.LoadValue(builder); ctx.LoadValue(oldList); ctx.EmitCall(addRange); if (addRange.ReturnType != null && add.ReturnType != voidType) { ctx.DiscardValue(); } } else { // loop and call Add repeatedly MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(ctx.Model, out moveNext, out current); Helpers.DebugAssert(moveNext != null); Helpers.DebugAssert(current != null); Helpers.DebugAssert(getEnumerator != null); Type enumeratorType = getEnumerator.ReturnType; using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType)) { ctx.LoadAddress(oldList, ExpectedType); ctx.EmitCall(getEnumerator); ctx.StoreValue(iter); using (ctx.Using(iter)) { Compiler.CodeLabel body = ctx.DefineLabel(), next = ctx.DefineLabel(); ctx.Branch(next, false); ctx.MarkLabel(body); ctx.LoadAddress(builder, builder.Type); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(current); ctx.EmitCall(add); if (add.ReturnType != null && add.ReturnType != voidType) { ctx.DiscardValue(); } ctx.MarkLabel(@next); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(moveNext); ctx.BranchIfTrue(body, false); } } } ctx.MarkLabel(done); } EmitReadList(ctx, builder, Tail, add, packedWireType, false); ctx.LoadAddress(builder, builder.Type); ctx.EmitCall(finish); if (ExpectedType != finish.ReturnType) { ctx.Cast(ExpectedType); } } }
private void WriteFieldHandler( Compiler.CompilerContext ctx, Type expected, Compiler.Local loc, Compiler.CodeLabel handler, Compiler.CodeLabel @continue, IProtoSerializer serializer) { ctx.MarkLabel(handler); Type serType = serializer.ExpectedType; if (serType == forType) { EmitCreateIfNull(ctx, loc); serializer.EmitRead(ctx, loc); } else { //RuntimeTypeModel rtm = (RuntimeTypeModel)ctx.Model; if (((IProtoTypeSerializer)serializer).CanCreateInstance()) { Compiler.CodeLabel allDone = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.BranchIfFalse(allDone, false); // null is always ok ctx.LoadValue(loc); ctx.TryCast(serType); ctx.BranchIfTrue(allDone, false); // not null, but of the correct type // otherwise, need to convert it ctx.LoadReaderWriter(); ctx.LoadValue(loc); ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("Merge")); ctx.Cast(expected); ctx.StoreValue(loc); // Merge always returns a value // nothing needs doing ctx.MarkLabel(allDone); } ctx.LoadValue(loc); ctx.Cast(serType); serializer.EmitRead(ctx, null); } if (serializer.ReturnsValue) { // update the variable ctx.StoreValue(loc); } ctx.Branch(@continue, false); // "continue" }
private object InvokeCallback(MethodInfo method, object obj, SerializationContext context) { object result = null; object[] args; if (method != null) { // pass in a streaming context if one is needed, else null bool handled; ParameterInfo[] parameters = method.GetParameters(); switch (parameters.Length) { case 0: args = null; handled = true; break; default: args = new object[parameters.Length]; handled = true; for (int i = 0; i < args.Length; i++) { object val; Type paramType = parameters[i].ParameterType; if (paramType == typeof(SerializationContext)) { val = context; } else if (paramType == typeof(System.Type)) { val = constructType; } #if PLAT_BINARYFORMATTER || (SILVERLIGHT && NET_4_0) else if (paramType == typeof(System.Runtime.Serialization.StreamingContext)) { val = (System.Runtime.Serialization.StreamingContext)context; } #endif else { val = null; handled = false; } args[i] = val; } break; } if (handled) { result = method.Invoke(obj, args); } else { throw Meta.CallbackSet.CreateInvalidCallbackSignature(method); } } return(result); }
public _Local(CodeGen owner, Type t) { _owner = owner; _t = t; _scope = owner.GetBlockForVariable(); }
public _Arg(int index, Type type) { _index = checked ((ushort)index); _type = type; }
public _Base(Type type) : base(0, type) { }
public ContextualOperand Local(Type type) { return(new ContextualOperand(new _Local(this, type), TypeMapper)); }
QualifiedType VisitType(IKVM.Reflection.Type managedType) { var isString = managedType.HasElementType && IKVM.Reflection.Type.GetTypeCode( managedType.GetElementType()) == TypeCode.String; if (managedType.IsByRef && isString) { managedType = managedType.GetElementType(); } // If true type is an array, a pointer, or is passed by reference. if (managedType.HasElementType) { var managedElementType = managedType.GetElementType(); var elementType = VisitType(managedElementType); if (managedType.IsByRef || managedType.IsPointer) { var ptrType = new PointerType(elementType) { Modifier = (Options.GeneratorKind == GeneratorKind.CPlusPlus) ? PointerType.TypeModifier.LVReference : PointerType.TypeModifier.Pointer }; return(new QualifiedType(ptrType)); } else if (managedType.IsArray) { if (elementType.Type.IsClass() || Options.GeneratorKind == GeneratorKind.Java) { return(new QualifiedType(new UnsupportedType { Description = managedType.FullName })); } var array = new ArrayType { SizeType = ArrayType.ArraySize.Variable, QualifiedType = elementType }; return(new QualifiedType(array)); } throw new NotImplementedException(); } if (managedType.IsEnum) { var @enum = Visit(managedType.GetTypeInfo()); return(new QualifiedType(new TagType(@enum))); } CppSharp.AST.Type type = null; TypeQualifiers qualifiers = new TypeQualifiers(); switch (IKVM.Reflection.Type.GetTypeCode(managedType)) { case TypeCode.Empty: type = new BuiltinType(PrimitiveType.Null); break; case TypeCode.Object: case TypeCode.Decimal: case TypeCode.DateTime: if (managedType.FullName == "System.Void") { type = new BuiltinType(PrimitiveType.Void); break; } var currentUnit = GetTranslationUnit(CurrentAssembly); if (managedType.Assembly.GetName().Name != currentUnit.FileNameWithoutExtension || managedType.IsGenericType) { type = new UnsupportedType { Description = managedType.FullName }; break; } var decl = Visit(managedType.GetTypeInfo()); type = new TagType(decl); break; case TypeCode.DBNull: type = new UnsupportedType() { Description = "DBNull" }; break; case TypeCode.Boolean: type = new BuiltinType(PrimitiveType.Bool); break; case TypeCode.Char: type = new BuiltinType(PrimitiveType.Char); break; case TypeCode.SByte: type = new BuiltinType(PrimitiveType.SChar); break; case TypeCode.Byte: type = new BuiltinType(PrimitiveType.UChar); break; case TypeCode.Int16: type = new BuiltinType(PrimitiveType.Short); break; case TypeCode.UInt16: type = new BuiltinType(PrimitiveType.UShort); break; case TypeCode.Int32: type = new BuiltinType(PrimitiveType.Int); break; case TypeCode.UInt32: type = new BuiltinType(PrimitiveType.UInt); break; case TypeCode.Int64: type = new BuiltinType(PrimitiveType.Long); break; case TypeCode.UInt64: type = new BuiltinType(PrimitiveType.ULong); break; case TypeCode.Single: type = new BuiltinType(PrimitiveType.Float); break; case TypeCode.Double: type = new BuiltinType(PrimitiveType.Double); break; case TypeCode.String: type = new BuiltinType(PrimitiveType.String); break; } return(new QualifiedType(type, qualifiers)); }
public BooleanSerializer(ProtoBuf.Meta.TypeModel model) { #if FEAT_IKVM expectedType = model.MapType(typeof(bool)); #endif }
public TypeSerializer(TypeModel model, Type forType, int[] fieldNumbers, IProtoSerializer[] serializers, MethodInfo[] baseCtorCallbacks, bool isRootType, bool useConstructor, CallbackSet callbacks, Type constructType, MethodInfo factory) { Helpers.DebugAssert(forType != null); Helpers.DebugAssert(fieldNumbers != null); Helpers.DebugAssert(serializers != null); Helpers.DebugAssert(fieldNumbers.Length == serializers.Length); Helpers.Sort(fieldNumbers, serializers); bool hasSubTypes = false; for (int i = 1; i < fieldNumbers.Length; i++) { if (fieldNumbers[i] == fieldNumbers[i - 1]) { throw new InvalidOperationException("Duplicate field-number detected; " + fieldNumbers[i].ToString() + " on: " + forType.FullName); } if (!hasSubTypes && serializers[i].ExpectedType != forType) { hasSubTypes = true; } } this.forType = forType; this.factory = factory; #if WINRT this.typeInfo = forType.GetTypeInfo(); #endif if (constructType == null) { constructType = forType; } else { #if WINRT if (!typeInfo.IsAssignableFrom(constructType.GetTypeInfo())) #else if (!forType.IsAssignableFrom(constructType)) #endif { throw new InvalidOperationException(forType.FullName + " cannot be assigned from " + constructType.FullName); } } this.constructType = constructType; this.serializers = serializers; this.fieldNumbers = fieldNumbers; this.callbacks = callbacks; this.isRootType = isRootType; this.useConstructor = useConstructor; if (baseCtorCallbacks != null && baseCtorCallbacks.Length == 0) { baseCtorCallbacks = null; } this.baseCtorCallbacks = baseCtorCallbacks; #if !NO_GENERICS if (Helpers.GetUnderlyingType(forType) != null) { throw new ArgumentException("Cannot create a TypeSerializer for nullable types", "forType"); } #endif #if WINRT if (iextensible.IsAssignableFrom(typeInfo)) { if (typeInfo.IsValueType || !isRootType || hasSubTypes) #else if (model.MapType(iextensible).IsAssignableFrom(forType)) { if (forType.IsValueType || !isRootType || hasSubTypes) #endif { throw new NotSupportedException("IExtensible is not supported in structs or classes with inheritance"); } isExtensible = true; } #if WINRT TypeInfo constructTypeInfo = constructType.GetTypeInfo(); hasConstructor = !constructTypeInfo.IsAbstract && Helpers.GetConstructor(constructTypeInfo, Helpers.EmptyTypes, true) != null; #else hasConstructor = !constructType.IsAbstract && Helpers.GetConstructor(constructType, Helpers.EmptyTypes, true) != null; #endif if (constructType != forType && useConstructor && !hasConstructor) { throw new ArgumentException("The supplied default implementation cannot be created: " + constructType.FullName, "constructType"); } }
public _Local(CodeGen owner, LocalBuilder var) { _owner = owner; _var = var; _t = var.LocalType; }
} // updates field directly #if FEAT_COMPILER void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { Type expected = ExpectedType; using (Compiler.Local loc = ctx.GetLocalWithValue(expected, valueFrom)) { // pre-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeSerialize); Compiler.CodeLabel startFields = ctx.DefineLabel(); // inheritance if (CanHaveInheritance) { for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; Type serType = ser.ExpectedType; if (serType != forType) { Compiler.CodeLabel ifMatch = ctx.DefineLabel(), nextTest = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.TryCast(serType); ctx.CopyValue(); ctx.BranchIfTrue(ifMatch, true); ctx.DiscardValue(); ctx.Branch(nextTest, true); ctx.MarkLabel(ifMatch); ser.EmitWrite(ctx, null); ctx.Branch(startFields, false); ctx.MarkLabel(nextTest); } } if (constructType != null && constructType != forType) { using (Compiler.Local actualType = new Compiler.Local(ctx, ctx.MapType(typeof(System.Type)))) { // would have jumped to "fields" if an expected sub-type, so two options: // a: *exactly* that type, b: an *unexpected* type ctx.LoadValue(loc); ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType")); ctx.CopyValue(); ctx.StoreValue(actualType); ctx.LoadValue(forType); ctx.BranchIfEqual(startFields, true); ctx.LoadValue(actualType); ctx.LoadValue(constructType); ctx.BranchIfEqual(startFields, true); } } else { // would have jumped to "fields" if an expected sub-type, so two options: // a: *exactly* that type, b: an *unexpected* type ctx.LoadValue(loc); ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType")); ctx.LoadValue(forType); ctx.BranchIfEqual(startFields, true); } // unexpected, then... note that this *might* be a proxy, which // is handled by ThrowUnexpectedSubtype ctx.LoadValue(forType); ctx.LoadValue(loc); ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType")); ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowUnexpectedSubtype", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)); } // fields ctx.MarkLabel(startFields); for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; if (ser.ExpectedType == forType) { ser.EmitWrite(ctx, loc); } } // extension data if (isExtensible) { ctx.LoadValue(loc); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("AppendExtensionData")); } // post-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.AfterSerialize); } }
string GetInternalTypeName(IKVM.Reflection.Type type) { // If true type is an array, a pointer, or is passed by reference. if (type.HasElementType) { var elementType = type.GetElementType(); if (type.IsArray) { return(GetInternalTypeName(elementType) + "[]"); } return(GetInternalTypeName(elementType)); } if (type.IsEnum) { return(type.FullName); } switch (IKVM.Reflection.Type.GetTypeCode(type)) { case TypeCode.Object: if (type.FullName == "System.IntPtr") { return("intptr"); } if (type.FullName == "System.UIntPtr") { return("uintptr"); } if (type.FullName == "System.Object") { return("object"); } return(type.FullName); case TypeCode.Boolean: return("bool"); case TypeCode.Char: return("char"); case TypeCode.SByte: return("sbyte"); case TypeCode.Byte: return("byte"); case TypeCode.Int16: return("int16"); case TypeCode.UInt16: return("uint16"); case TypeCode.Int32: return("int"); case TypeCode.UInt32: return("uint"); case TypeCode.Int64: return("long"); case TypeCode.UInt64: return("ulong"); case TypeCode.Single: return("single"); case TypeCode.Double: return("double"); case TypeCode.String: return("string"); case TypeCode.Empty: return("null"); case TypeCode.DBNull: case TypeCode.Decimal: case TypeCode.DateTime: return(type.FullName); } throw new NotImplementedException("No implementation for " + type); }
public object Read(object value, ProtoReader source) { if (isRootType && value != null) { Callback(value, TypeModel.CallbackType.BeforeDeserialize, source.Context); } int fieldNumber, lastFieldNumber = 0, lastFieldIndex = 0; bool fieldHandled; //Helpers.DebugWriteLine(">> Reading fields for " + forType.FullName); while ((fieldNumber = source.ReadFieldHeader()) > 0) { fieldHandled = false; if (fieldNumber < lastFieldNumber) { lastFieldNumber = lastFieldIndex = 0; } for (int i = lastFieldIndex; i < fieldNumbers.Length; i++) { if (fieldNumbers[i] == fieldNumber) { IProtoSerializer ser = serializers[i]; //Helpers.DebugWriteLine(": " + ser.ToString()); Type serType = ser.ExpectedType; if (value == null) { if (serType == forType) { value = CreateInstance(source, true); } } else { if (serType != forType && ((IProtoTypeSerializer)ser).CanCreateInstance() && serType #if WINRT .GetTypeInfo() #endif .IsSubclassOf(value.GetType())) { value = ProtoReader.Merge(source, value, ((IProtoTypeSerializer)ser).CreateInstance(source)); } } if (ser.ReturnsValue) { value = ser.Read(value, source); } else // pop { ser.Read(value, source); } lastFieldIndex = i; lastFieldNumber = fieldNumber; fieldHandled = true; break; } } if (!fieldHandled) { //Helpers.DebugWriteLine(": [" + fieldNumber + "] (unknown)"); if (value == null) { value = CreateInstance(source, true); } if (isExtensible) { source.AppendExtensionData((IExtensible)value); } else { source.SkipField(); } } } //Helpers.DebugWriteLine("<< Reading fields for " + forType.FullName); if (value == null) { value = CreateInstance(source, true); } if (isRootType) { Callback(value, TypeModel.CallbackType.AfterDeserialize, source.Context); } return(value); }
void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { Type expected = ExpectedType; Helpers.DebugAssert(valueFrom != null); using (Compiler.Local loc = ctx.GetLocalWithValue(expected, valueFrom)) using (Compiler.Local fieldNumber = new Compiler.Local(ctx, ctx.MapType(typeof(int)))) { // pre-callbacks if (HasCallbacks(TypeModel.CallbackType.BeforeDeserialize)) { if (ExpectedType.IsValueType) { EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeDeserialize); } else { // could be null Compiler.CodeLabel callbacksDone = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.BranchIfFalse(callbacksDone, false); EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeDeserialize); ctx.MarkLabel(callbacksDone); } } Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel(); ctx.Branch(@continue, false); ctx.MarkLabel(processField); foreach (BasicList.Group group in BasicList.GetContiguousGroups(fieldNumbers, serializers)) { Compiler.CodeLabel tryNextField = ctx.DefineLabel(); int groupItemCount = group.Items.Count; if (groupItemCount == 1) { // discreet group; use an equality test ctx.LoadValue(fieldNumber); ctx.LoadValue(group.First); Compiler.CodeLabel processThisField = ctx.DefineLabel(); ctx.BranchIfEqual(processThisField, true); ctx.Branch(tryNextField, false); WriteFieldHandler(ctx, expected, loc, processThisField, @continue, (IProtoSerializer)group.Items[0]); } else { // implement as a jump-table-based switch ctx.LoadValue(fieldNumber); ctx.LoadValue(group.First); ctx.Subtract(); // jump-tables are zero-based Compiler.CodeLabel[] jmp = new Compiler.CodeLabel[groupItemCount]; for (int i = 0; i < groupItemCount; i++) { jmp[i] = ctx.DefineLabel(); } ctx.Switch(jmp); // write the default... ctx.Branch(tryNextField, false); for (int i = 0; i < groupItemCount; i++) { WriteFieldHandler(ctx, expected, loc, jmp[i], @continue, (IProtoSerializer)group.Items[i]); } } ctx.MarkLabel(tryNextField); } EmitCreateIfNull(ctx, loc); ctx.LoadReaderWriter(); if (isExtensible) { ctx.LoadValue(loc); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData")); } else { ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); } ctx.MarkLabel(@continue); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(fieldNumber); ctx.LoadValue(0); ctx.BranchIfGreater(processField, false); EmitCreateIfNull(ctx, loc); // post-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.AfterDeserialize); if (valueFrom != null && !loc.IsSame(valueFrom)) { ctx.LoadValue(loc); ctx.Cast(valueFrom.Type); ctx.StoreValue(valueFrom); } } }
internal static bool IdentifyImmutable(TypeModel model, Type declaredType, out MethodInfo builderFactory, out MethodInfo add, out MethodInfo addRange, out MethodInfo finish) { builderFactory = add = addRange = finish = null; if (model == null || declaredType == null) { return(false); } #if WINRT TypeInfo declaredTypeInfo = declaredType.GetTypeInfo(); #else Type declaredTypeInfo = declaredType; #endif // try to detect immutable collections; firstly, they are all generic, and all implement IReadOnlyCollection<T> for some T if (!declaredTypeInfo.IsGenericType) { return(false); } #if WINRT Type[] typeArgs = declaredTypeInfo.GenericTypeArguments, effectiveType; #else Type[] typeArgs = declaredTypeInfo.GetGenericArguments(), effectiveType; #endif switch (typeArgs.Length) { case 1: effectiveType = typeArgs; break; // fine case 2: Type kvp = model.MapType(typeof(System.Collections.Generic.KeyValuePair <,>)); if (kvp == null) { return(false); } kvp = kvp.MakeGenericType(typeArgs); effectiveType = new Type[] { kvp }; break; default: return(false); // no clue! } if (ResolveIReadOnlyCollection(declaredType, null) == null) { return(false); // no IReadOnlyCollection<T> found } // and we want to use the builder API, so for generic Foo<T> or IFoo<T> we want to use Foo.CreateBuilder<T> string name = declaredType.Name; int i = name.IndexOf('`'); if (i <= 0) { return(false); } name = declaredTypeInfo.IsInterface ? name.Substring(1, i - 1) : name.Substring(0, i); Type outerType = model.GetType(declaredType.Namespace + "." + name, declaredTypeInfo.Assembly); // I hate special-cases... if (outerType == null && name == "ImmutableSet") { outerType = model.GetType(declaredType.Namespace + ".ImmutableHashSet", declaredTypeInfo.Assembly); } if (outerType == null) { return(false); } #if WINRT foreach (MethodInfo method in outerType.GetTypeInfo().DeclaredMethods) #else foreach (MethodInfo method in outerType.GetMethods()) #endif { if (!method.IsStatic || method.Name != "CreateBuilder" || !method.IsGenericMethodDefinition || method.GetParameters().Length != 0 || method.GetGenericArguments().Length != typeArgs.Length) { continue; } builderFactory = method.MakeGenericMethod(typeArgs); break; } Type voidType = model.MapType(typeof(void)); if (builderFactory == null || builderFactory.ReturnType == null || builderFactory.ReturnType == voidType) { return(false); } add = Helpers.GetInstanceMethod(builderFactory.ReturnType, "Add", effectiveType); if (add == null) { return(false); } finish = Helpers.GetInstanceMethod(builderFactory.ReturnType, "ToImmutable", Helpers.EmptyTypes); if (finish == null || finish.ReturnType == null || finish.ReturnType == voidType) { return(false); } if (!(finish.ReturnType == declaredType || Helpers.IsAssignableFrom(declaredType, finish.ReturnType))) { return(false); } addRange = Helpers.GetInstanceMethod(builderFactory.ReturnType, "AddRange", new Type[] { declaredType }); if (addRange == null) { Type enumerable = model.MapType(typeof(System.Collections.Generic.IEnumerable <>), false); if (enumerable != null) { addRange = Helpers.GetInstanceMethod(builderFactory.ReturnType, "AddRange", new Type[] { enumerable.MakeGenericType(effectiveType) }); } } return(true); }
void IProtoTypeSerializer.EmitCallback(Compiler.CompilerContext ctx, Compiler.Local valueFrom, TypeModel.CallbackType callbackType) { bool actuallyHasInheritance = false; if (CanHaveInheritance) { for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; if (ser.ExpectedType != forType && ((IProtoTypeSerializer)ser).HasCallbacks(callbackType)) { actuallyHasInheritance = true; } } } Helpers.DebugAssert(((IProtoTypeSerializer)this).HasCallbacks(callbackType), "Shouldn't be calling this if there is nothing to do"); MethodInfo method = callbacks == null ? null : callbacks[callbackType]; if (method == null && !actuallyHasInheritance) { return; } ctx.LoadAddress(valueFrom, ExpectedType); EmitInvokeCallback(ctx, method, actuallyHasInheritance, null, forType); if (actuallyHasInheritance) { Compiler.CodeLabel @break = ctx.DefineLabel(); for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; IProtoTypeSerializer typeser; Type serType = ser.ExpectedType; if (serType != forType && (typeser = (IProtoTypeSerializer)ser).HasCallbacks(callbackType)) { Compiler.CodeLabel ifMatch = ctx.DefineLabel(), nextTest = ctx.DefineLabel(); ctx.CopyValue(); ctx.TryCast(serType); ctx.CopyValue(); ctx.BranchIfTrue(ifMatch, true); ctx.DiscardValue(); ctx.Branch(nextTest, false); ctx.MarkLabel(ifMatch); typeser.EmitCallback(ctx, null, callbackType); ctx.Branch(@break, false); ctx.MarkLabel(nextTest); } } ctx.MarkLabel(@break); ctx.DiscardValue(); } }
protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom)) { MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(ctx.Model, out moveNext, out current); Helpers.DebugAssert(moveNext != null); Helpers.DebugAssert(current != null); Helpers.DebugAssert(getEnumerator != null); Type enumeratorType = getEnumerator.ReturnType; bool writePacked = WritePacked; using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType)) using (Compiler.Local token = writePacked ? new Compiler.Local(ctx, ctx.MapType(typeof(SubItemToken))) : null) { if (writePacked) { ctx.LoadValue(fieldNumber); ctx.LoadValue((int)WireType.String); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("WriteFieldHeader")); ctx.LoadValue(list); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("StartSubItem")); ctx.StoreValue(token); ctx.LoadValue(fieldNumber); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("SetPackedField")); } ctx.LoadAddress(list, ExpectedType); ctx.EmitCall(getEnumerator); ctx.StoreValue(iter); using (ctx.Using(iter)) { Compiler.CodeLabel body = ctx.DefineLabel(), next = ctx.DefineLabel(); ctx.Branch(next, false); ctx.MarkLabel(body); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(current); Type itemType = Tail.ExpectedType; if (itemType != ctx.MapType(typeof(object)) && current.ReturnType == ctx.MapType(typeof(object))) { ctx.CastFromObject(itemType); } Tail.EmitWrite(ctx, null); ctx.MarkLabel(@next); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(moveNext); ctx.BranchIfTrue(body, false); } if (writePacked) { ctx.LoadValue(token); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("EndSubItem")); } } } }
protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { Type listType; #if NO_GENERICS listType = typeof(BasicList); #else listType = ctx.MapType(typeof(System.Collections.Generic.List <>)).MakeGenericType(itemType); #endif Type expected = ExpectedType; using (Compiler.Local oldArr = AppendToCollection ? ctx.GetLocalWithValue(expected, valueFrom) : null) using (Compiler.Local newArr = new Compiler.Local(ctx, expected)) using (Compiler.Local list = new Compiler.Local(ctx, listType)) { ctx.EmitCtor(listType); ctx.StoreValue(list); ListDecorator.EmitReadList(ctx, list, Tail, listType.GetMethod("Add"), packedWireType, false); // leave this "using" here, as it can share the "FieldNumber" local with EmitReadList using (Compiler.Local oldLen = AppendToCollection ? new ProtoBuf.Compiler.Local(ctx, ctx.MapType(typeof(int))) : null) { Type[] copyToArrayInt32Args = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) }; if (AppendToCollection) { ctx.LoadLength(oldArr, true); ctx.CopyValue(); ctx.StoreValue(oldLen); ctx.LoadAddress(list, listType); ctx.LoadValue(listType.GetProperty("Count")); ctx.Add(); ctx.CreateArray(itemType, null); // length is on the stack ctx.StoreValue(newArr); ctx.LoadValue(oldLen); Compiler.CodeLabel nothingToCopy = ctx.DefineLabel(); ctx.BranchIfFalse(nothingToCopy, true); ctx.LoadValue(oldArr); ctx.LoadValue(newArr); ctx.LoadValue(0); // index in target ctx.EmitCall(expected.GetMethod("CopyTo", copyToArrayInt32Args)); ctx.MarkLabel(nothingToCopy); ctx.LoadValue(list); ctx.LoadValue(newArr); ctx.LoadValue(oldLen); } else { ctx.LoadAddress(list, listType); ctx.LoadValue(listType.GetProperty("Count")); ctx.CreateArray(itemType, null); ctx.StoreValue(newArr); ctx.LoadAddress(list, listType); ctx.LoadValue(newArr); ctx.LoadValue(0); } copyToArrayInt32Args[0] = expected; // // prefer: CopyTo(T[], int) MethodInfo copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args); if (copyTo == null) { // fallback: CopyTo(Array, int) copyToArrayInt32Args[1] = ctx.MapType(typeof(Array)); copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args); } ctx.EmitCall(copyTo); } ctx.LoadValue(newArr); } }
private static void EmitReadAndAddItem(Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add, bool castListForAdd) { ctx.LoadAddress(list, list.Type); // needs to be the reference in case the list is value-type (static-call) if (castListForAdd) { ctx.Cast(add.DeclaringType); } Type itemType = tail.ExpectedType; bool tailReturnsValue = tail.ReturnsValue; if (tail.RequiresOldValue) { if (Helpers.IsValueType(itemType) || !tailReturnsValue) { // going to need a variable using (Compiler.Local item = new Compiler.Local(ctx, itemType)) { if (Helpers.IsValueType(itemType)) { // initialise the struct ctx.LoadAddress(item, itemType); ctx.EmitCtor(itemType); } else { // assign null ctx.LoadNullRef(); ctx.StoreValue(item); } tail.EmitRead(ctx, item); if (!tailReturnsValue) { ctx.LoadValue(item); } } } else { // no variable; pass the null on the stack and take the value *off* the stack ctx.LoadNullRef(); tail.EmitRead(ctx, null); } } else { if (tailReturnsValue) { // out only (on the stack); just emit it tail.EmitRead(ctx, null); } else { // doesn't take anything in nor return anything! WTF? throw new InvalidOperationException(); } } // our "Add" is chosen either to take the correct type, or to take "object"; // we may need to box the value Type addParamType = add.GetParameters()[0].ParameterType; if (addParamType != itemType) { if (addParamType == ctx.MapType(typeof(object))) { ctx.CastToObject(itemType); } #if !NO_GENERICS else if (Helpers.GetUnderlyingType(addParamType) == itemType) { // list is nullable ConstructorInfo ctor = Helpers.GetConstructor(addParamType, new Type[] { itemType }, false); ctx.EmitCtor(ctor); // the itemType on the stack is now a Nullable<ItemType> } #endif else { throw new InvalidOperationException("Conflicting item/add type"); } } ctx.EmitCall(add); if (add.ReturnType != ctx.MapType(typeof(void))) { ctx.DiscardValue(); } }
void AppendCATypeName(StringBuilder sb, Type type, string typeName, bool securityCompatHack = false) { if (type.IsArray) { AppendCATypeName(sb, type.GetElementType(), null); sb.Append("[]"); } else if (type == typeofSystemBoolean) { sb.Append("bool"); } else if (type == typeofSystemSByte) { sb.Append("int8"); } else if (type == typeofSystemByte) { sb.Append("uint8"); } else if (type == typeofSystemChar) { sb.Append("char"); } else if (type == typeofSystemInt16) { sb.Append("int16"); } else if (type == typeofSystemUInt16) { sb.Append("uint16"); } else if (type == typeofSystemInt32) { sb.Append("int32"); } else if (type == typeofSystemUInt32) { sb.Append("uint32"); } else if (type == typeofSystemInt64) { sb.Append("int64"); } else if (type == typeofSystemUInt64) { sb.Append("uint64"); } else if (type == typeofSystemSingle) { sb.Append("float32"); } else if (type == typeofSystemDouble) { sb.Append("float64"); } else if (type == typeofSystemString) { sb.Append("string"); } else if (type == typeofSystemObject) { sb.Append("object"); } else if (type.FullName == "System.Type" && type.Assembly.GetName().Name == "mscorlib") { sb.Append("type"); } else { sb.Append("enum "); AppendTypeName(sb, type, typeName, false, securityCompatHack); } }
public ArrayDecorator(TypeModel model, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, Type arrayType, bool overwriteList, bool supportNull) : base(tail) { Helpers.DebugAssert(arrayType != null, "arrayType should be non-null"); Helpers.DebugAssert(arrayType.IsArray && arrayType.GetArrayRank() == 1, "should be single-dimension array; " + arrayType.FullName); this.itemType = arrayType.GetElementType(); #if NO_GENERICS Type underlyingItemType = itemType; #else Type underlyingItemType = supportNull ? itemType : (Helpers.GetUnderlyingType(itemType) ?? itemType); #endif Helpers.DebugAssert(underlyingItemType == Tail.ExpectedType || (Tail.ExpectedType.ToString() == typeof(object).ToString() && !Helpers.IsValueType(underlyingItemType)), "invalid tail"); Helpers.DebugAssert(Tail.ExpectedType != model.MapType(typeof(byte)), "Should have used BlobSerializer"); if ((writePacked || packedWireType != WireType.None) && fieldNumber <= 0) { throw new ArgumentOutOfRangeException("fieldNumber"); } if (!ListDecorator.CanPack(packedWireType)) { if (writePacked) { throw new InvalidOperationException("Only simple data-types can use packed encoding"); } packedWireType = WireType.None; } this.fieldNumber = fieldNumber; this.packedWireType = packedWireType; if (writePacked) { options |= OPTIONS_WritePacked; } if (overwriteList) { options |= OPTIONS_OverwriteList; } if (supportNull) { options |= OPTIONS_SupportNull; } this.arrayType = arrayType; }
protected ListDecorator(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull) : base(tail) { if (returnList) { options |= OPTIONS_ReturnList; } if (overwriteList) { options |= OPTIONS_OverwriteList; } if (supportNull) { options |= OPTIONS_SupportNull; } if ((writePacked || packedWireType != WireType.None) && fieldNumber <= 0) { throw new ArgumentOutOfRangeException("fieldNumber"); } if (!CanPack(packedWireType)) { if (writePacked) { throw new InvalidOperationException("Only simple data-types can use packed encoding"); } packedWireType = WireType.None; } this.fieldNumber = fieldNumber; if (writePacked) { options |= OPTIONS_WritePacked; } this.packedWireType = packedWireType; if (declaredType == null) { throw new ArgumentNullException("declaredType"); } if (declaredType.IsArray) { throw new ArgumentException("Cannot treat arrays as lists", "declaredType"); } this.declaredType = declaredType; this.concreteType = concreteType; // look for a public list.Add(typedObject) method if (RequireAdd) { bool isList; add = TypeModel.ResolveListAdd(model, declaredType, tail.ExpectedType, out isList); if (isList) { options |= OPTIONS_IsList; string fullName = declaredType.FullName; if (fullName != null && fullName.StartsWith("System.Data.Linq.EntitySet`1[[")) { // see http://stackoverflow.com/questions/6194639/entityset-is-there-a-sane-reason-that-ilist-add-doesnt-set-assigned options |= OPTIONS_SuppressIList; } } if (add == null) { throw new InvalidOperationException("Unable to resolve a suitable Add method for " + declaredType.FullName); } } }
bool Compare(Type a, Type b) { return(a == b || a.IsGenericType && b.IsGenericType && a.GetGenericTypeDefinition() == b.GetGenericTypeDefinition()); }
static void EmitInvokeCallback(Compiler.CompilerContext ctx, MethodInfo method, bool copyValue, Type constructType, Type type) { if (method != null) { if (copyValue) { ctx.CopyValue(); // assumes the target is on the stack, and that we want to *retain* it on the stack } ParameterInfo[] parameters = method.GetParameters(); bool handled = true; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[0].ParameterType; if (parameterType == ctx.MapType(typeof(SerializationContext))) { ctx.LoadSerializationContext(); } else if (parameterType == ctx.MapType(typeof(System.Type))) { Type tmp = constructType; if (tmp == null) { tmp = type; // no ?? in some C# profiles } ctx.LoadValue(tmp); } #if PLAT_BINARYFORMATTER else if (parameterType == ctx.MapType(typeof(System.Runtime.Serialization.StreamingContext))) { ctx.LoadSerializationContext(); MethodInfo op = ctx.MapType(typeof(SerializationContext)).GetMethod("op_Implicit", new Type[] { ctx.MapType(typeof(SerializationContext)) }); if (op != null) { // it isn't always! (framework versions, etc) ctx.EmitCall(op); handled = true; } } #endif else { handled = false; } } if (handled) { ctx.EmitCall(method); if (constructType != null) { if (method.ReturnType == ctx.MapType(typeof(object))) { ctx.CastFromObject(type); } } } else { throw Meta.CallbackSet.CreateInvalidCallbackSignature(method); } } }
public DecimalSerializer(ProtoBuf.Meta.TypeModel model) { #if FEAT_IKVM expectedType = model.MapType(typeof(decimal)); #endif }
void ReadFixedArg(StringBuilder sb, ByteReader br, Type type, bool arrayElement = false) { if (type.IsArray) { int length = br.ReadInt32(); if (length == -1 && compat == CompatLevel.None) { sb.Append("nullref"); } else if (length == 0 && compat != CompatLevel.None) { throw new IKVM.Reflection.BadImageFormatException(); } else { Type elementType = type.GetElementType(); AppendCATypeName(sb, elementType, null); sb.AppendFormat("[{0}](", length); for (int i = 0; i < length; i++) { if (i != 0) { sb.Append(' '); } if (elementType == typeofSystemObject) { string typeName; ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName), false); } else { ReadFixedArg(sb, br, elementType, true); } } sb.Append(')'); } } else if (type.FullName == "System.Type" && type.Assembly.GetName().Name == "mscorlib") { if (!arrayElement) { AppendCATypeName(sb, type, null); sb.Append('('); } string typeName; var type1 = ReadType(br, out typeName); if (type1 == null) { if (typeName == null) { sb.Append("nullref"); } else { sb.Append("class ").Append(QuoteIdentifier(typeName, true)); } } else { AppendTypeName(sb, type1, typeName, compat != CompatLevel.None && IsNestedTypeWithNamespace(type1)); } if (!arrayElement) { sb.Append(')'); } } else if (type.Assembly == mscorlib) { if (!arrayElement) { AppendCATypeName(sb, type, null); sb.Append('('); } if (type == typeofSystemBoolean) { sb.Append(br.ReadByte() == 0 ? "false" : "true"); } else if (type == typeofSystemByte) { sb.Append(br.ReadByte()); } else if (type == typeofSystemSByte) { sb.Append(br.ReadSByte()); } else if (type == typeofSystemChar) { sb.AppendFormat("0x{0:X4}", (int)br.ReadChar()); } else if (type == typeofSystemInt16) { sb.Append(br.ReadInt16()); } else if (type == typeofSystemUInt16) { sb.Append(br.ReadUInt16()); } else if (type == typeofSystemInt32) { sb.Append(br.ReadInt32()); } else if (type == typeofSystemUInt32) { sb.Append(br.ReadInt32()); } else if (type == typeofSystemInt64) { sb.Append(br.ReadInt64()); } else if (type == typeofSystemUInt64) { sb.Append(br.ReadInt64()); } else if (type == typeofSystemSingle) { sb.Append(ToString(br.ReadSingle(), true)); } else if (type == typeofSystemDouble) { sb.Append(ToString(br.ReadDouble(), true)); } else if (type == typeofSystemString) { var str = br.ReadString(); if (str == null) { sb.Append("nullref"); } else { if (compat != CompatLevel.None) { int pos = str.IndexOf((char)0); if (pos != -1) { str = str.Substring(0, pos); } } sb.Append(QuoteIdentifier(str, true)); } } else if (type == typeofSystemObject) { string typeName; ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName)); } else { throw new NotImplementedException(type.FullName); } if (!arrayElement) { sb.Append(')'); } } else if (type.__IsMissing || (compat != CompatLevel.None && typerefs.Contains(type))) { // ildasm actually tries to load the assembly, but we can't do that, so we cheat by having // a list of 'known' enum types if (type.Assembly.GetName().Name == "mscorlib") { switch (type.FullName) { case "System.AttributeTargets": case "System.Runtime.ConstrainedExecution.Consistency": case "System.Runtime.ConstrainedExecution.Cer": case "System.Security.Permissions.SecurityAction": case "System.Security.Permissions.SecurityPermissionFlag": case "System.Runtime.Versioning.ResourceScope": case "System.Runtime.InteropServices.CallingConvention": case "System.Runtime.InteropServices.CharSet": ReadFixedArg(sb, br, typeofSystemInt32); return; case "System.Security.SecurityRuleSet": if (compat != CompatLevel.V20) { ReadFixedArg(sb, br, typeofSystemByte); return; } break; case "System.Diagnostics.Tracing.EventLevel": case "System.Diagnostics.Tracing.EventTask": case "System.Diagnostics.Tracing.EventOpcode": if (compat != CompatLevel.V20 && compat != CompatLevel.V40) { ReadFixedArg(sb, br, typeofSystemInt32); return; } break; case "System.Type": sb.Append("type("); string typeName; AppendTypeName(sb, ReadType(br, out typeName), typeName); sb.Append(")"); return; } } switch (br.Length) { case 1: if (compat != CompatLevel.None) { // ildasm uses bool (???) as the underlying type in this case sb.AppendFormat("bool({0})", br.ReadByte() == 0 ? "false" : "true"); } else { // just guess that the enum has int8 as the underlying type sb.AppendFormat("int8({0})", br.ReadSByte()); } break; case 2: // just guess that the enum has int16 as the underlying type sb.AppendFormat("int16({0})", br.ReadInt16()); break; case 4: // just guess that the enum has int32 as the underlying type sb.AppendFormat("int32({0})", br.ReadInt32()); break; case 8: // just guess that the enum has int64 as the underlying type sb.AppendFormat("int64({0})", br.ReadInt64()); break; default: throw new IKVM.Reflection.BadImageFormatException(); } } else if (type.IsEnum) { ReadFixedArg(sb, br, type.GetEnumUnderlyingType(), arrayElement); } else { throw new NotImplementedException(type.FullName); } }