Skip to content

Instantly share code, notes, and snippets.

@searler
searler / DecoderGather.scala
Created July 20, 2015 01:32
Self contained ByteString scodec decoder mechanism
import akka.util.ByteString
import scodec.Attempt.Successful
import scodec.DecodeResult
import scodec.Decoder
import scodec.bits.BitVector
class DecoderGather[R](decoder: Decoder[R]) {
private var bitBuffer = BitVector.empty
def apply(chunk: ByteString): Seq[R] = {
@searler
searler / subtypeEncoding.scala
Created August 1, 2015 21:52
Using scodec discriminated/typecase to encode subtypes
val contents: Codec[Data] = discriminated[Data].by(ignore(0))
.typecase((), empty)
.typecase((), XXX)
.typecase((), YYY)
)
@searler
searler / XorChecksumCodec.scala
Created August 1, 2015 22:10
scodec XOR checksum Codec
object XorChecksumCodec {
def xorByte(bits: BitVector): BitVector = BitVector(bits.bytes.foldLeft[Byte](0)((a, b) => (a ^ b).asInstanceOf[Byte]))
def apply[T](target: Codec[T]) = checksummed(target, xorByte, trailer(target), true)
def trailer[T](target: Codec[T]): Codec[(BitVector, BitVector)] = new Codec[(BitVector, BitVector)] {
def sizeBound = target.sizeBound + new SizeBound(0, Some(8L))
def encode(value: (BitVector, BitVector)): Attempt[BitVector] = Attempt.successful(value._1 ++ value._2)
def decode(bits: BitVector): Attempt[DecodeResult[(BitVector, BitVector)]] =
@searler
searler / ByteVectorCodec.scala
Created August 10, 2015 22:47
A trivial convenience mechanism to map between BitVector and ByteVector
import scodec.Codec
import scodec.bits.ByteVector
object ByteVectorCodec extends Codec[ByteVector] {
import scodec.{ Attempt, DecodeResult }
import scodec.SizeBound
import scodec.bits.BitVector
def sizeBound = new SizeBound(0, None)
@searler
searler / ByteStringCodec.scala
Created August 10, 2015 22:48
A trivial convenience Codec to map between Akka ByteString and scodec BitVector
import scodec.Codec
import akka.util.ByteString
object ByteStringCodec extends Codec[ByteString] {
import scodec.{ Attempt, DecodeResult }
import scodec.SizeBound
import scodec.bits.BitVector
def sizeBound = new SizeBound(0, None)
import scodec.Decoder
import scodec.bits.BitVector
import scodec.Err
import scodec.Attempt
import scodec.DecodeResult
class FixedSizeDecoder[A](sizeBytes: Long, decoder: Decoder[A]) extends Decoder[A] {
val size = sizeBytes * 8
@searler
searler / Bracketed.scala
Created February 29, 2016 23:55
Bracket scodec with start and end markers
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)))
}
@searler
searler / Command.scala
Created June 15, 2016 02:04
Akka HTTP command route using Objects
def command(marker:Command) = path("app" / "command" / marker.toString) {
post {
entity(as[String]) { _ =>
actorRef ! marker
complete(StatusCodes.OK)
}
}
}
@searler
searler / Configure.scala
Created June 15, 2016 02:10
Akka HTTP one way configuration command using case classes
def configure[T <: Config](implicit tag: ClassTag[T], convert:FromRequestUnmarshaller[T]) = path("app" / "configure" / tag.runtimeClass.getSimpleName) {
post {
entity(as[T]) { c =>
actorRef ! c
complete(StatusCodes.OK)
}
}
}
trait Config
@searler
searler / MarshalString.scala
Created June 16, 2016 23:01
Marshalling a simple case class to/from string representation for Akka HTTP
case class A(code:Int)
import akka.http.scaladsl.marshalling.PredefinedToEntityMarshallers._
import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers._
implicit val aResponseUnmarshaller = stringUnmarshaller.map {s:String => A(s.toInt) }
implicit val aResponseMarshaller = StringMarshaller.compose{p:A => p.code.toString}