Skip to content

Instantly share code, notes, and snippets.

@bwmcadams
Forked from mpilquist/document.scala
Created March 3, 2016 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bwmcadams/ed5e3858d9e664a35923 to your computer and use it in GitHub Desktop.
Save bwmcadams/ed5e3858d9e664a35923 to your computer and use it in GitHub Desktop.
Example of using scodec to decode a document of fields
package foo
import scodec.bits._
import scodec._
import scodec.codecs._
case class Document(fields: Vector[(String, Field)])
sealed trait Field
case class IntField(value: Int) extends Field
case class StringField(value: String) extends Field
object Document {
val field: Codec[(String, Field)] = {
discriminated[(String, Field)].by(uint8).
subcaseO(1) { case (nme, fld: IntField) => Some(nme -> fld); case _ => None } (cstring ~ int32.as[IntField]).
subcaseO(2) { case (nme, fld: StringField) => Some(nme -> fld); case _ => None } (cstring ~ cstring.as[StringField])
}
def nullTerminated[A](c: Codec[A]): Codec[A] = new Codec[A] {
def sizeBound = c.sizeBound + SizeBound.exact(8)
def encode(a: A) = c.encode(a).map { _ ++ hex"00".bits }
def decode(b: BitVector) = {
if (b.takeRight(8) == hex"00".bits)
c.decode(b.dropRight(8))
else Attempt.failure(Err("Was not null terminated!"))
}
}
val codec: Codec[Document] = {
nullTerminated(variableSizeBytes(int32, vector(field), 4).as[Document])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment