Partial and asynchronous deserialization c# with protobuf-net -


context

i'm have file following structure:

[protocontract] public class data {     [protomember(1)]     public string header { get; set; }      [protomember(2)]     public byte[] body { get; set; } } 

the code reads / writes data file running on asp.net mvc webapi context. i'm trying keep every blocking io async minimize blocking , achieve best scalability. reading , writing files support readasync, writeasync , copytoasync.

the body can reasonably large (>> header) , need read body if header matches specific criteria.

i can partially read , deserialize header synchronously , read , deserialize body same way using approach explained in deserialize part of binary file

problem

how can use asynchronous file io same, reading , deserializing header async , reading , deserializing body same way?

i've read asynchronous protobuf serialization not option.

technically protobuf fields can out-of-order, in cases (including 1 show) can reasonable assume fields in-order (the way them out-of-order here separately serialize 2 half-classes , concatenate results, technically valid in protobuf specification).

so; have is:

  • a varint denoting: field 1, string - decimal 10
  • a varint denoting "a", length of header
  • "a" bytes, utf-8 encoded header
  • a varint denoting: field 2, string - decimal 18
  • a varint denoting "b", length of body
  • "b" bytes, body

we can assume "a" >= 0 , < int.maxvalue - means take @ 5 bytes encode; so, if buffer at least 6 bytes, have enough information know how large header is. of course, technically contain part of body, you'd need keep hold of it! if had sync-over-async stream, can read just part of stream like:

int protoheader = protoreader.directreadvarintint32(stream); // 10 int headerlength = protoreader.directreadvarintint32(stream); string header = protoreader.directreadstring(stream, headerlength); 

or if "sync on async" tricky, explicit reading:

static byte[] readatleast6() {     return new byte[] { 0x0a, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f }; } static byte[] readmore(int bytes) {     return new byte[] { 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 }; } static void main() {     // pretend read 7 bytes async     var data = readatleast6();     using (var ms = new memorystream())     {         ms.write(data, 0, data.length);         ms.position = 0;         int protoheader = protoreader.directreadvarintint32(ms); // 10         int headerlength = protoreader.directreadvarintint32(ms); // 11          int needed = (headerlength + (int)ms.position) - data.length; // 6 more         var pos = ms.position;         ms.seek(0, seekorigin.end);         data = readmore(needed);         ms.write(data, 0, needed);         ms.position = pos;         string header = protoreader.directreadstring(ms, headerlength);     } } 

Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -