Skip to content

Instantly share code, notes, and snippets.

@searler
searler / CustomZLogger.scala
Created January 23, 2022 16:24
Adding custom ZLogger to capture unhandled defects
// https://github.com/zio/zio/issues/6278
import zio.{Cause, FiberId, FiberRef, LogLevel, LogSpan, RuntimeConfigAspect, ZIO, ZIOAppDefault, ZLogger, ZTraceElement}
object Example extends ZIOAppDefault {
val specialLogger: ZLogger[Cause[Any], Unit] =
(
trace: ZTraceElement,
fiberId: FiberId,
@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}
@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 / 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 / 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)))
}
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 / 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)
@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 / 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 / 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)
)