Exemplo n.º 1
0
 internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull)
 {
     if (returnList && ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out MethodInfo builderFactory, out MethodInfo methodInfo, out MethodInfo addRange, out MethodInfo finish))
     {
         return(new ImmutableCollectionDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, builderFactory, methodInfo, addRange, finish));
     }
     return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull));
 }
Exemplo n.º 2
0
        internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull, bool dontThrowNullReference)
        {
#if !NO_GENERICS
            MethodInfo builderFactory, add, addRange, finish;
            if (returnList && ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out builderFactory, out add, out addRange, out finish))
            {
                return(new ImmutableCollectionDecorator(
                           model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, dontThrowNullReference,
                           builderFactory, add, addRange, finish));
            }
#endif
            return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, dontThrowNullReference));
        }
Exemplo n.º 3
0
        internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull)
        {
            MethodInfo methodInfo;
            MethodInfo methodInfo1;
            MethodInfo methodInfo2;
            MethodInfo methodInfo3;

            if (!returnList || !ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out methodInfo, out methodInfo1, out methodInfo2, out methodInfo3))
            {
                return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull));
            }
            return(new ImmutableCollectionDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, methodInfo, methodInfo1, methodInfo2, methodInfo3));
        }
Exemplo n.º 4
0
        // Token: 0x06003574 RID: 13684 RVA: 0x001345BC File Offset: 0x001329BC
        internal static bool IdentifyImmutable(TypeModel model, Type declaredType, out MethodInfo builderFactory, out MethodInfo add, out MethodInfo addRange, out MethodInfo finish)
        {
            MethodInfo methodInfo;

            finish         = methodInfo = null;
            addRange       = methodInfo;
            add            = methodInfo;
            builderFactory = methodInfo;
            if (model == null || declaredType == null)
            {
                return(false);
            }
            if (!declaredType.IsGenericType)
            {
                return(false);
            }
            Type[] genericArguments = declaredType.GetGenericArguments();
            int    num = genericArguments.Length;

            Type[] array;
            if (num != 1)
            {
                if (num != 2)
                {
                    return(false);
                }
                Type type = model.MapType(typeof(KeyValuePair <, >));
                if (type == null)
                {
                    return(false);
                }
                type  = type.MakeGenericType(genericArguments);
                array = new Type[]
                {
                    type
                };
            }
            else
            {
                array = genericArguments;
            }
            if (ImmutableCollectionDecorator.ResolveIReadOnlyCollection(declaredType, null) == null)
            {
                return(false);
            }
            string text = declaredType.Name;
            int    num2 = text.IndexOf('`');

            if (num2 <= 0)
            {
                return(false);
            }
            text = ((!declaredType.IsInterface) ? text.Substring(0, num2) : text.Substring(1, num2 - 1));
            Type type2 = model.GetType(declaredType.Namespace + "." + text, declaredType.Assembly);

            if (type2 == null && text == "ImmutableSet")
            {
                type2 = model.GetType(declaredType.Namespace + ".ImmutableHashSet", declaredType.Assembly);
            }
            if (type2 == null)
            {
                return(false);
            }
            foreach (MethodInfo methodInfo2 in type2.GetMethods())
            {
                if (methodInfo2.IsStatic && !(methodInfo2.Name != "CreateBuilder") && methodInfo2.IsGenericMethodDefinition && methodInfo2.GetParameters().Length == 0 && methodInfo2.GetGenericArguments().Length == genericArguments.Length)
                {
                    builderFactory = methodInfo2.MakeGenericMethod(genericArguments);
                    break;
                }
            }
            Type type3 = model.MapType(typeof(void));

            if (builderFactory == null || builderFactory.ReturnType == null || builderFactory.ReturnType == type3)
            {
                return(false);
            }
            add = Helpers.GetInstanceMethod(builderFactory.ReturnType, "Add", array);
            if (add == null)
            {
                return(false);
            }
            finish = Helpers.GetInstanceMethod(builderFactory.ReturnType, "ToImmutable", Helpers.EmptyTypes);
            if (finish == null || finish.ReturnType == null || finish.ReturnType == type3)
            {
                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 type4 = model.MapType(typeof(IEnumerable <>), false);
                if (type4 != null)
                {
                    addRange = Helpers.GetInstanceMethod(builderFactory.ReturnType, "AddRange", new Type[]
                    {
                        type4.MakeGenericType(array)
                    });
                }
            }
            return(true);
        }
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            MethodInfo methodInfo;
            MethodInfo methodInfo1;
            Local      localWithValue;

            if (base.AppendToCollection)
            {
                localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom);
            }
            else
            {
                localWithValue = null;
            }
            using (Local local = localWithValue)
            {
                using (Local local1 = new Local(ctx, this.builderFactory.ReturnType))
                {
                    ctx.EmitCall(this.builderFactory);
                    ctx.StoreValue(local1);
                    if (base.AppendToCollection)
                    {
                        CodeLabel codeLabel = ctx.DefineLabel();
                        if (!this.ExpectedType.IsValueType)
                        {
                            ctx.LoadValue(local);
                            ctx.BranchIfFalse(codeLabel, false);
                        }
                        PropertyInfo property = Helpers.GetProperty(this.ExpectedType, "Length", false) ?? Helpers.GetProperty(this.ExpectedType, "Count", false) ?? Helpers.GetProperty(ImmutableCollectionDecorator.ResolveIReadOnlyCollection(this.ExpectedType, this.Tail.ExpectedType), "Count", false);
                        ctx.LoadAddress(local, local.Type);
                        ctx.EmitCall(Helpers.GetGetMethod(property, false, false));
                        ctx.BranchIfFalse(codeLabel, false);
                        Type type = ctx.MapType(typeof(void));
                        if (this.addRange == null)
                        {
                            MethodInfo enumeratorInfo = base.GetEnumeratorInfo(ctx.Model, out methodInfo, out methodInfo1);
                            Type       returnType     = enumeratorInfo.ReturnType;
                            using (Local local2 = new Local(ctx, returnType))
                            {
                                ctx.LoadAddress(local, this.ExpectedType);
                                ctx.EmitCall(enumeratorInfo);
                                ctx.StoreValue(local2);
                                using (IDisposable disposable = ctx.Using(local2))
                                {
                                    CodeLabel codeLabel1 = ctx.DefineLabel();
                                    CodeLabel codeLabel2 = ctx.DefineLabel();
                                    ctx.Branch(codeLabel2, false);
                                    ctx.MarkLabel(codeLabel1);
                                    ctx.LoadAddress(local1, local1.Type);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo1);
                                    ctx.EmitCall(this.@add);
                                    if ([email protected] != null && [email protected] != type)
                                    {
                                        ctx.DiscardValue();
                                    }
                                    ctx.MarkLabel(codeLabel2);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo);
                                    ctx.BranchIfTrue(codeLabel1, false);
                                }
                            }
                        }
                        else
                        {
                            ctx.LoadValue(local1);
                            ctx.LoadValue(local);
                            ctx.EmitCall(this.addRange);
                            if (this.addRange.ReturnType != null && [email protected] != type)
                            {
                                ctx.DiscardValue();
                            }
                        }
                        ctx.MarkLabel(codeLabel);
                    }
                    ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, false);
                    ctx.LoadAddress(local1, local1.Type);
                    ctx.EmitCall(this.finish);
                    if (this.ExpectedType != this.finish.ReturnType)
                    {
                        ctx.Cast(this.ExpectedType);
                    }
                }
            }
        }
        internal static bool IdentifyImmutable(TypeModel model, Type declaredType, out MethodInfo builderFactory, out MethodInfo add, out MethodInfo addRange, out MethodInfo finish)
        {
            Type[]     typeArray;
            object     obj        = null;
            MethodInfo methodInfo = (MethodInfo)obj;

            finish = (MethodInfo)obj;
            MethodInfo methodInfo1 = methodInfo;
            MethodInfo methodInfo2 = methodInfo1;

            addRange = methodInfo1;
            MethodInfo methodInfo3 = methodInfo2;
            MethodInfo methodInfo4 = methodInfo3;

            add            = methodInfo3;
            builderFactory = methodInfo4;
            if (model == null || declaredType == null)
            {
                return(false);
            }
            Type type = declaredType;

            if (!type.IsGenericType)
            {
                return(false);
            }
            Type[] genericArguments = type.GetGenericArguments();
            switch ((int)genericArguments.Length)
            {
            case 1:
            {
                typeArray = genericArguments;
                break;
            }

            case 2:
            {
                Type type1 = model.MapType(typeof(KeyValuePair <,>));
                if (type1 == null)
                {
                    return(false);
                }
                type1     = type1.MakeGenericType(genericArguments);
                typeArray = new Type[] { type1 };
                break;
            }

            default:
            {
                return(false);
            }
            }
            if (ImmutableCollectionDecorator.ResolveIReadOnlyCollection(declaredType, null) == null)
            {
                return(false);
            }
            string name = declaredType.Name;
            int    num  = name.IndexOf('\u0060');

            if (num <= 0)
            {
                return(false);
            }
            name = (type.IsInterface ? name.Substring(1, num - 1) : name.Substring(0, num));
            Type type2 = model.GetType(string.Concat(declaredType.Namespace, ".", name), type.Assembly);

            if (type2 == null && name == "ImmutableSet")
            {
                type2 = model.GetType(string.Concat(declaredType.Namespace, ".ImmutableHashSet"), type.Assembly);
            }
            if (type2 == null)
            {
                return(false);
            }
            MethodInfo[] methods = type2.GetMethods();
            int          num1    = 0;

            while (num1 < (int)methods.Length)
            {
                MethodInfo methodInfo5 = methods[num1];
                if (!methodInfo5.IsStatic || methodInfo5.Name != "CreateBuilder" || !methodInfo5.IsGenericMethodDefinition || (int)methodInfo5.GetParameters().Length != 0 || (int)methodInfo5.GetGenericArguments().Length != (int)genericArguments.Length)
                {
                    num1++;
                }
                else
                {
                    builderFactory = methodInfo5.MakeGenericMethod(genericArguments);
                    break;
                }
            }
            Type type3 = model.MapType(typeof(void));

            if (builderFactory == null || builderFactory.ReturnType == null || builderFactory.ReturnType == type3)
            {
                return(false);
            }
            add = Helpers.GetInstanceMethod(builderFactory.ReturnType, "Add", typeArray);
            if (add == null)
            {
                return(false);
            }
            finish = Helpers.GetInstanceMethod(builderFactory.ReturnType, "ToImmutable", Helpers.EmptyTypes);
            if (finish == null || finish.ReturnType == null || finish.ReturnType == type3)
            {
                return(false);
            }
            if (finish.ReturnType != declaredType && !Helpers.IsAssignableFrom(declaredType, finish.ReturnType))
            {
                return(false);
            }
            Type returnType = builderFactory.ReturnType;

            Type[] typeArray1 = new Type[] { declaredType };
            addRange = Helpers.GetInstanceMethod(returnType, "AddRange", typeArray1);
            if (addRange == null)
            {
                Type type4 = model.MapType(typeof(IEnumerable <>), false);
                if (type4 != null)
                {
                    Type   returnType1 = builderFactory.ReturnType;
                    Type[] typeArray2  = new Type[] { type4.MakeGenericType(typeArray) };
                    addRange = Helpers.GetInstanceMethod(returnType1, "AddRange", typeArray2);
                }
            }
            return(true);
        }