starry/starry/src/main/scala/tf/bug/starry/Bytable.scala

77 lines
2.1 KiB
Scala

package tf.bug.starry
import scodec.bits.ByteVector
import shapeless.{::, HList, HNil, ProductTypeClass, ProductTypeClassCompanion}
import spire.math.UByte
import tf.bug.nose.{Color, ColorFormat}
trait Bytable[T] {
def apply(t: T): ByteVector
}
object Bytable extends BytableImplicits
trait BytableImplicits extends ProductTypeClassCompanion[Bytable] {
implicit class BytableOps[T](t: T)(implicit ev: Bytable[T]) {
def asBytes: ByteVector = ev(t)
}
implicit def messageAsBytable[P, M <: Message[P]]: Bytable[M] =
new Bytable[M] {
override def apply(t: M): ByteVector = {
import t.payloadEv
t.length.asBytes ++ t.id.asBytes ++ t.payload.asBytes
}
}
implicit def stringAsBytable: Bytable[String] = new Bytable[String] {
override def apply(t: String): ByteVector = {
ByteVector(t.getBytes("UTF-8"))
}
}
implicit def uByteAsBytable: Bytable[UByte] = new Bytable[UByte] {
override def apply(t: UByte): ByteVector = ByteVector.fromByte(t.signed)
}
implicit def intAsBytable: Bytable[Int] = new Bytable[Int] {
override def apply(t: Int): ByteVector = ByteVector.fromInt(t)
}
implicit def listAsBytable[A: Bytable]: Bytable[List[A]] =
new Bytable[List[A]] {
override def apply(t: List[A]): ByteVector =
t.map(_.asBytes).foldLeft(ByteVector.empty)(_ ++ _)
}
implicit def colorAsBytable: Bytable[Color] = new Bytable[Color] {
override def apply(t: Color): ByteVector = {
val f = t.rgb
List(f.red, f.green, f.blue).map(d => UByte((d * 255).toInt)).asBytes
}
}
object typeClass extends ProductTypeClass[Bytable] {
override def product[H, T <: HList](ch: Bytable[H], ct: Bytable[T]): Bytable[H :: T] =
new Bytable[H :: T] {
override def apply(t: H :: T): ByteVector = ch(t.head) ++ ct(t.tail)
}
override def emptyProduct: Bytable[HNil] = new Bytable[HNil] {
override def apply(t: HNil): ByteVector = ByteVector.empty
}
override def project[F, G](instance: => Bytable[G], to: F => G, from: G => F): Bytable[F] = new Bytable[F] {
override def apply(t: F): ByteVector = instance(to(t))
}
}
}