77 lines
2.1 KiB
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))
|
|
}
|
|
|
|
}
|
|
|
|
}
|