I am writing a performance-oriented data deserializer by emitting IL. The serialized data is UTF8
, and the fields are denoted as strings.
[FieldA]: 22
[FieldB]: 16
I have already written a custom reader that properly tokenizes the serialized data and provides a ReadOnlySpan<byte>
as it steps through the serialized data.
I would like to have a static, inline deserializer that is able to have the byte signatures of the fields packed in so that I can easily create a jump table and set the appropriate fields.
How non-dynamic code might look:
// byteSpan is a ReadOnlySpan<byte> containing the signature
var signatureA = Encoding.UTF8.GetBytes( "FieldA" );
var signatureB = Encoding.UTF8.GetBytes( "FieldB" );
if( byteSpan.SequenceEqual( signatureA ) )
DoSomething();
else if ( byteSpan.SequenceEqual( signatureB ) )
DoSomething();
...
How the jump table is being emitted:
var fieldSignatures = GetTypeSignatures<T>(); // Returns a Tuple<byte[], FieldInfo>
var setFieldLabels = new List<Tuple<FieldInfo, Label>>();
foreach( (byte[] signature, FieldInfo field) in fieldSignatures )
{
var setFieldLabel = il.DefineLabel();
setFieldLabels.Add( Tuple.Create( field, setFieldLabel ) );
il.Emit( OpCodes.Ldloc_1 ); // Load the current ReadOnlySpan<byte>
// Inline load byte[] signature here
il.Emit( OpCodes.Call, METHOD_SEQUENCEEQUAL );
il.Emit( OpCodes.Brtrue, setFieldLabel );
}
EmitFieldSetters( setFieldLabels, ref il );
Is there a way I can bake the signature byte arrays directly into the IL that I am emitting so that they are a part of the delegate?
These signatures are generated at runtime based on type information, so manually defining them in a static class isn't feasible. A workaround could be to define a new dynamic Assembly
and Type
and store the bytes in there, but I would like to avoid having to do that if possible.
Aucun commentaire:
Enregistrer un commentaire