public void EmitDeserialize(CompilerContext context, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArrayLabel = context.Emit.DefineLabel(); var endLabel = context.Emit.DefineLabel(); using (var length = context.Emit.DeclareLocal <int>("length")) { // length = ProudNetBinaryReaderExtensions.ReadScalar(reader) context.Emit.LoadReaderOrWriterParam(); context.Emit.Call(ReflectionHelper.GetMethod((BinaryReader _) => _.ReadScalar())); context.Emit.StoreLocal(length); // if(length < 1) { // value = Array.Empty<>() // return // } context.Emit.LoadLocal(length); context.Emit.LoadConstant(1); context.Emit.BranchIfLess(emptyArrayLabel); // value = new [length] context.Emit.LoadLocal(length); context.Emit.NewArray(elementType); context.Emit.StoreLocal(value); // Little optimization for byte arrays if (elementType == typeof(byte)) { // value = reader.ReadBytes(length); context.Emit.LoadReaderOrWriterParam(); context.Emit.LoadLocal(length); context.Emit.Call(ReflectionHelper.GetMethod((BinaryReader _) => _.ReadBytes(default(int)))); context.Emit.StoreLocal(value); } else { var loopLabel = context.Emit.DefineLabel(); var loopCheckLabel = context.Emit.DefineLabel(); using (var element = context.Emit.DeclareLocal(elementType, "element")) using (var i = context.Emit.DeclareLocal <int>("i")) { context.Emit.MarkLabel(loopLabel); context.EmitDeserialize(element); // value[i] = element context.Emit.LoadLocal(value); context.Emit.LoadLocal(i); context.Emit.LoadLocal(element); context.Emit.StoreElement(elementType); // ++i context.Emit.LoadLocal(i); context.Emit.LoadConstant(1); context.Emit.Add(); context.Emit.StoreLocal(i); // i < length context.Emit.MarkLabel(loopCheckLabel); context.Emit.LoadLocal(i); context.Emit.LoadLocal(length); context.Emit.BranchIfLess(loopLabel); } } context.Emit.Branch(endLabel); } // value = Array.Empty<>() context.Emit.MarkLabel(emptyArrayLabel); context.Emit.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); context.Emit.StoreLocal(value); context.Emit.MarkLabel(endLabel); }
public void EmitDeserialize(CompilerContext context, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArray = context.Emit.DefineLabel(); var end = context.Emit.DefineLabel(); using (var length = context.Emit.DeclareLocal <int>("length")) { context.EmitDeserialize(length); // if(length < 1) { // value = Array.Empty<>() // return // } context.Emit.LoadLocal(length); context.Emit.LoadConstant(1); context.Emit.BranchIfLess(emptyArray); // value = new [length] context.Emit.LoadLocal(length); context.Emit.NewArray(elementType); context.Emit.StoreLocal(value); var loop = context.Emit.DefineLabel(); var loopCheck = context.Emit.DefineLabel(); using (var element = context.Emit.DeclareLocal(elementType, "element")) using (var i = context.Emit.DeclareLocal <int>("i")) { context.Emit.MarkLabel(loop); // reader.ReadByte() -> index context.Emit.LoadReaderOrWriterParam(); context.Emit.CallVirtual(ReflectionHelper.GetMethod((BinaryReader _) => _.ReadByte())); context.Emit.Pop(); context.EmitDeserialize(element); // value[i] = element context.Emit.LoadLocal(value); context.Emit.LoadLocal(i); context.Emit.LoadLocal(element); context.Emit.StoreElement(elementType); // ++i context.Emit.LoadLocal(i); context.Emit.LoadConstant(1); context.Emit.Add(); context.Emit.StoreLocal(i); // i < length context.Emit.MarkLabel(loopCheck); context.Emit.LoadLocal(i); context.Emit.LoadLocal(length); context.Emit.BranchIfLess(loop); } context.Emit.Branch(end); } // value = Array.Empty<>() context.Emit.MarkLabel(emptyArray); context.Emit.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); context.Emit.StoreLocal(value); context.Emit.MarkLabel(end); }