Skip to content

Instantly share code, notes, and snippets.

@searler
Created February 29, 2016 23:55
Show Gist options
  • Save searler/3892e21d413c0867b543 to your computer and use it in GitHub Desktop.
Save searler/3892e21d413c0867b543 to your computer and use it in GitHub Desktop.
Bracket scodec with start and end markers

Generalization of cstring combinator

def bracketed[T](start:BitVector, end:BitVector, extract: Codec[T]): Codec[T] = filtered(extract, new Codec[BitVector] {
override def sizeBound: SizeBound = SizeBound.unknown
override def encode(bits: BitVector): Attempt[BitVector] = Attempt.successful(start ++ bits ++ end)
override def decode(bits: BitVector): Attempt[DecodeResult[BitVector]] = {
bits.bytes.indexOfSlice(start.bytes) match {
case -1 => Attempt.failure(Err("Does not contain start."))
case si => bits.bytes.indexOfSlice(end.bytes) match {
case -1 => Attempt.failure(Err("Does not contain end."))
case ei => Attempt.successful(DecodeResult(bits.slice((si + start.size) * 8L, ei * 8L), bits.drop((ei + end.size) * 8L)))
}
}
}
}).withToString("bracketed")
import org.scalatest._
import scodec.bits.BitVector
import scodec.DecodeResult
import scodec.Attempt.Successful
import scodec.Decoder
import scodec.codecs._
import Codecs._
class CodecTest extends FlatSpec with Matchers {
val string: Decoder[String] = bracketed(BitVector(2),BitVector(3, 0),ascii)
"simple string" should "extract" in {
val bv = BitVector("\u0002xxx\u0003\u0000".getBytes)
string.decode(bv) match {
case Successful(DecodeResult(value, remainder)) =>
value should be("xxx")
remainder should be(BitVector.empty)
case _@ x => fail(x.toString)
}
}
"prefixed string" should "extract" in {
val bv = BitVector("aaa\u0002xxx\u0003\u0000".getBytes)
string.decode(bv) match {
case Successful(DecodeResult(value, remainder)) =>
value should be("xxx")
remainder should be(BitVector.empty)
case _@ x => fail(x.toString)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment