public void EmitWrite(WriterEmitContext context) { var nullable = typeof(TPrimitive?); var il = context.Il; var hasValue = il.DefineLabel(); var end = il.DefineLabel(); context.LoadValue(); il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .HasValue)).GetGetMethod(), null); il.Emit(OpCodes.Brtrue_S, hasValue); // no value, just store 0 and return length = 1 if (context.HasManifestToWrite == false) { context.LoadBuffer(); il.LoadIntValue(0); il.Emit(OpCodes.Stind_I1); il.LoadIntValue(1); il.Emit(OpCodes.Br, end); // jump to the end of writing } else { il.LoadIntValue(0); il.Emit(OpCodes.Br, end); // jump to the end of writing } // has value, store 1, then store value il.MarkLabel(hasValue); if (context.HasManifestToWrite == false) { context.LoadBuffer(); il.LoadIntValue(1); il.Emit(OpCodes.Stind_I1); il.LoadIntValue(1); context.AddToCurrentOffset(); } else { context.WriteManifest(); } // load shifted buffer and value context.LoadBuffer(); context.LoadValue(); il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .Value)).GetGetMethod(), null); // emit regular Emit(context); il.MarkLabel(end); }
public void EmitWrite(WriterEmitContext context) { context.LoadBuffer(); context.LoadValue(); EmitWriteImpl(context); }
void EmitNonNullWriter(WriterEmitContext ctx) { var il = ctx.Il; if (ctx.HasManifestToWrite) { ctx.WriteManifest(); } using (ctx.GetLocal <int>(out var offset)) { ctx.LoadCurrentOffset(); il.Store(offset); // add 2 for the length of variable il.LoadIntValue(2); ctx.AddToCurrentOffset(); Writer.EmitWrite(ctx); // stack empty, value written directly to the buffer ctx.LoadBuffer(offset); // stack: byte* ctx.LoadCurrentOffset(); il.Load(offset); il.Emit(OpCodes.Sub); // stack: byte*, value il.LoadIntValue(2); il.Emit(OpCodes.Sub); // -2 for length il.StoreIndirectLittleEndian(typeof(short)); // save length } }
void EmitClassWriter(WriterEmitContext ctx) { var il = ctx.Il; var nullLbl = il.DefineLabel(); var end = il.DefineLabel(); ctx.LoadValue(); il.Emit(OpCodes.Brfalse, nullLbl); EmitNonNullWriter(ctx); il.Emit(OpCodes.Br, end); // writing null il.MarkLabel(nullLbl); if (ctx.HasManifestToWrite == false) { ctx.LoadBuffer(); il.LoadIntValue(NullLength); il.StoreIndirectLittleEndian(typeof(short)); il.LoadIntValue(2); // used only 2 bytes for writing null ctx.AddToCurrentOffset(); } else { // no value, nothing to write } il.MarkLabel(end); }
public void EmitWrite(WriterEmitContext context) { context.LoadBuffer(); context.LoadValue(); context.CallWriteStringUnsafe(); context.AddToCurrentOffset(); }
public void WriteManifest() { if (HasManifestToWrite) { context.LoadBuffer(); context.Il.LoadIntValue(manifest.Value); context.Il.StoreIndirectLittleEndian(typeof(short)); context.Il.LoadIntValue(2); context.AddToCurrentOffset(); } else { throw new Exception("No manifest to write"); } }
public void EmitWrite(WriterEmitContext context) { var il = context.Il; using (context.GetLocal <int>(out var length)) { context.LoadValue(); il.EmitCall(OpCodes.Call, typeof(Span <byte>).GetProperty(nameof(Span <byte> .Length)).GetGetMethod(), null); il.Store(length); context.LoadValue(); // stack: span context.LoadBuffer(); // stack: span, buffer il.Load(length); // stack: span, buffer, length il.Emit(OpCodes.Newobj, typeof(Span <byte>).GetConstructor(new[] { typeof(void).MakePointerType(), typeof(int) })); //stack: span-source, span-dest il.EmitCall(OpCodes.Call, typeof(Span <byte>).GetMethod(nameof(Span <byte> .CopyTo)), null); il.Load(length); context.AddToCurrentOffset(); } }