Scodec: How to create a codec for an optional byte -


i must create codec message has following specification message length indicated byte of least significant bit extension flag that, when set indicates following (optional) byte must used significant byte. (hope make sense) can depicted follows:

 +----------------------------------------------------------------------------------+ |                                    length                                        | |                                                                                  | +----------------------------------+-----+-+---------------------------------------+ |                                  |     | |                                       | |               len1 (lsb)         | ext | |         len2 (msb) - optional         | +----+----+----+----+----+----+----+-----+ +----+----+----+----+----+----+----+----+ |    |    |    |    |    |    |    |     | |    |    |    |    |    |    |    |    | |    |    |    |    |    |    |    |  +  | |    |    |    |    |    |    |    |    | +----+----+----+----+----+----+----+--|--+ +----+----+----+----+----+----+----+----+                                       |                                       |                                       v                         boolean: if true len2 used                                 else len1     

the length of data follow determined field(s). use codec along predefined codecs , combinators. guess involve using flatzip not clear on how incorporate flatzip hlist combinator. pointers examples or documentation appreciated.

one way using scodec.codecs.optional combinator, returns codec[option[a]] given codec[boolean] , codec[a].

val structure: codec[(int, option[int])] = uint(7) ~ optional(bool, uint8) 

this gives codec of (int, option[int]) - need convert codec of int. so, we'll need provide conversion int (int, option[int]) , conversion in reverse direction. know size field @ 2^15 - 1 (7 lsb bits , 8 msb bits), converting (int, option[int]) int total, whereas converting in reverse direction possibly fail -- example, 2^16 cannot represented in structure. hence, can use widen conversion:

val size: codec[int] = structure.widen[int](   { case (lsb, msb) => lsb + msb.map(_ << 7).getorelse(0) },   { sz =>      val msb = sz >>> 7     if (msb > 255 || msb < 0) attempt.failure(err(s"invalid size $sz"))     else attempt.successful((sz & 0x7f, if (msb > 0) some(msb) else none))   }) 

finally, can use size codec encode variable length structure via variablesizebytes:

val str: codec[string] = variablesizebytes(size, ascii) 

this gives codec[string] prefixes encoded string bytes size in bytes, encoded according scheme defined above.


Comments

Popular posts from this blog

c++ - Difference between pre and post decrement in recursive function argument -

php - Nothing but 'run(); ' when browsing to my local project, how do I fix this? -

php - How can I echo out this array? -