protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { Type listType; #if NO_GENERICS listType = typeof(BasicList); #else listType = typeof(System.Collections.Generic.List <>).MakeGenericType(itemType); #endif using (Compiler.Local oldArr = ctx.GetLocalWithValue(ExpectedType, valueFrom)) using (Compiler.Local newArr = new Compiler.Local(ctx, ExpectedType)) using (Compiler.Local list = new Compiler.Local(ctx, listType)) { ctx.EmitCtor(listType); ctx.StoreValue(list); ListDecorator.EmitReadList(ctx, list, Tail, listType.GetMethod("Add"), packedWireType); // leave this "using" here, as it can share the "FieldNumber" local with EmitReadList using (Compiler.Local oldLen = new ProtoBuf.Compiler.Local(ctx, typeof(int))) { 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(oldLen); Type[] argTypes = new Type[] { typeof(Array), typeof(int) }; ctx.EmitCall(ExpectedType.GetMethod("CopyTo", argTypes)); ctx.MarkLabel(nothingToCopy); ctx.LoadValue(list); ctx.LoadValue(newArr); ctx.LoadValue(oldLen); argTypes[0] = ExpectedType; // // prefer: CopyTo(T[], int) MethodInfo copyTo = listType.GetMethod("CopyTo", argTypes); if (copyTo == null) { // fallback: CopyTo(Array, int) argTypes[1] = typeof(Array); copyTo = listType.GetMethod("CopyTo", argTypes); } ctx.EmitCall(copyTo); } ctx.LoadValue(newArr); } }
protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { Type listType; listType = ctx.MapType(typeof(System.Collections.Generic.List <>)).MakeGenericType(itemType); 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); } }
protected override void EmitRead(CompilerContext ctx, Local valueFrom) { Local localWithValue; Local local; Type type = ctx.MapType(typeof(List <>)); Type[] typeArray = new Type[] { this.itemType }; Type type1 = type.MakeGenericType(typeArray); Type expectedType = this.ExpectedType; if (this.AppendToCollection) { localWithValue = ctx.GetLocalWithValue(expectedType, valueFrom); } else { localWithValue = null; } using (Local local1 = localWithValue) { using (Local local2 = new Local(ctx, expectedType)) { using (Local local3 = new Local(ctx, type1)) { ctx.EmitCtor(type1); ctx.StoreValue(local3); ListDecorator.EmitReadList(ctx, local3, this.Tail, type1.GetMethod("Add"), this.packedWireType, false); if (this.AppendToCollection) { local = new Local(ctx, ctx.MapType(typeof(int))); } else { local = null; } using (Local local4 = local) { Type[] typeArray1 = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) }; Type[] typeArray2 = typeArray1; if (!this.AppendToCollection) { ctx.LoadAddress(local3, type1); ctx.LoadValue(type1.GetProperty("Count")); ctx.CreateArray(this.itemType, null); ctx.StoreValue(local2); ctx.LoadAddress(local3, type1); ctx.LoadValue(local2); ctx.LoadValue(0); } else { ctx.LoadLength(local1, true); ctx.CopyValue(); ctx.StoreValue(local4); ctx.LoadAddress(local3, type1); ctx.LoadValue(type1.GetProperty("Count")); ctx.Add(); ctx.CreateArray(this.itemType, null); ctx.StoreValue(local2); ctx.LoadValue(local4); CodeLabel codeLabel = ctx.DefineLabel(); ctx.BranchIfFalse(codeLabel, true); ctx.LoadValue(local1); ctx.LoadValue(local2); ctx.LoadValue(0); ctx.EmitCall(expectedType.GetMethod("CopyTo", typeArray2)); ctx.MarkLabel(codeLabel); ctx.LoadValue(local3); ctx.LoadValue(local2); ctx.LoadValue(local4); } typeArray2[0] = expectedType; MethodInfo method = type1.GetMethod("CopyTo", typeArray2); if (method == null) { typeArray2[1] = ctx.MapType(typeof(Array)); method = type1.GetMethod("CopyTo", typeArray2); } ctx.EmitCall(method); } ctx.LoadValue(local2); } } } }
protected override void EmitRead(CompilerContext ctx, Local valueFrom) { Local local; bool returnList = this.ReturnList; using (Local local1 = (this.AppendToCollection ? ctx.GetLocalWithValue(this.ExpectedType, valueFrom) : new Local(ctx, this.declaredType))) { if (!returnList || !this.AppendToCollection) { local = null; } else { local = new Local(ctx, this.ExpectedType); } using (Local local2 = local) { if (!this.AppendToCollection) { ctx.LoadNullRef(); ctx.StoreValue(local1); } else if (returnList) { ctx.LoadValue(local1); ctx.StoreValue(local2); } if (this.concreteType != null) { ctx.LoadValue(local1); CodeLabel codeLabel = ctx.DefineLabel(); ctx.BranchIfTrue(codeLabel, true); ctx.EmitCtor(this.concreteType); ctx.StoreValue(local1); ctx.MarkLabel(codeLabel); } bool flag = [email protected](this.declaredType); ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, flag); if (returnList) { if (!this.AppendToCollection) { ctx.LoadValue(local1); } else { ctx.LoadValue(local2); ctx.LoadValue(local1); CodeLabel codeLabel1 = ctx.DefineLabel(); CodeLabel codeLabel2 = ctx.DefineLabel(); ctx.BranchIfEqual(codeLabel1, true); ctx.LoadValue(local1); ctx.Branch(codeLabel2, true); ctx.MarkLabel(codeLabel1); ctx.LoadNullRef(); ctx.MarkLabel(codeLabel2); } } } } }
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); } } } }