我正在尝试为scodec库编写一个组合器,它将Codec[K]in转换为Codec[L]where K是a HList并且与删除的所有元素L等效.HListUnit
实现解码可以通过解码a K然后过滤掉所有Unit元素来完成.过滤掉Unit元素直接由无形使用支持filterNot,这使得实现这一点变得微不足道.
实现编码是通过将La 转换为a K,()在适当的索引处插入,然后委托给原始代码来完成的Codec[K].我在实现L => K转换时遇到了麻烦.
def dropUnits[K <: HList, L <: HList](codec: Codec[K])(
implicit fltr: FilterNot.Aux[K, Unit, L]): Codec[L] = new Codec[L] {
override def decode(buffer: BitVector) =
codec.decode(buffer).map { case (rest, l) => (rest, l.filterNot[Unit]) }
override def encode(xs: L) = {
???
}
}
Run Code Online (Sandbox Code Playgroud)
没有运气,我尝试了几种不同的解决方案.这可能是无形的吗?
我正在寻找一种方法来处理如下例子的协议:
case class Request(bodyType: Int, foo: Int, bar: Int, body: RequestBody)
sealed trait RequestBody
case class Read(key: String) extends RequestBody
case class Write(key: String, value: Array[Byte]) extends RequestBody
Run Code Online (Sandbox Code Playgroud)
在这里,bodyType == 0将代表Read,bodyType != 0并将编码Write.注意,有一些字段将鉴别器与鉴别值分开.
我见过一个带字节排序的例子.但据我所知,这种"鱿鱼"编码鉴别器不会往返.解决这个问题的正确方法是什么?
作为SCodec的新用户,有一个相当的学习曲线.尽管阅读了源代码和文档,我还是遇到了一些似乎无法解决的问题.
我希望能够将流行的编解码器定义为这样的函数
def packedByte : Codec[Int :: Int :: Int :: HNil] = uint(4) :: uint(2) :: uint(2)
Run Code Online (Sandbox Code Playgroud)
然后将它们组合到更高级别的编解码器中,这样可以对像这样的case类进行解码和编码
case class MyPacket(foo : Boolean, first : Int, second : Int, third : Int, bar : Boolean)
def packet : Codec[MyPacket] = (bool :: packedByte :: bool).as[MyPacket]
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用
无法证明自己没有形状.:[布尔,无形.:无形.:[Int,Shapeless.::] Int,Shapeless.:::Int ,shapeless .HNil]]],形状::[布尔,shapeless.HNil]]]可以转换为/从cmd504.MyPacket.
然而,当我"内联"时packedByte,就像
def packetInline : Codec[MyPacket] = (bool :: uint(4) :: uint(2) :: uint(2) :: bool).as[MyPacket]
Run Code Online (Sandbox Code Playgroud)
一切都按预期编译和工作.我的直觉告诉我,编解码器必须"扁平化"(基于错误消息中的两个HNils),但我无法压缩编解码器本身或内部HList表示.
在版本上:
"org.typelevel" %% "scodec-core" % "1.5.0"
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用coproduct功能,如测试用例中所示,将编解码器修复为已知的子类型.
我一直收到错误:"找不到参数auto的隐含值:scodec.codecs.CoproductBuilderAuto [my.class.here]"
我甚至复制粘贴的例子,无法让它工作:
import scalaz.\/
import shapeless._
import scodec.bits._
import scodec.codecs._
import scodec._
sealed trait Sprocket
object Sprocket {
implicit val discriminated: Discriminated[Sprocket, Int] = Discriminated(uint8)
}
def codec(d: Int): Codec[Sprocket] = Codec.coproduct[Sprocket].discriminatedBy(provide(d)).auto
Run Code Online (Sandbox Code Playgroud)
我会在最后继续研究这个问题,但是想知道最近是否有一个问题已经解决了.我克隆了repo,它从克隆开始工作 - 但是当我使用发布的版本时却没有.
在Scala中读取和编写C风格字节结构的最佳方法是什么,如下所示:
struct account {
int id;
char[10] data1;
char[10] data2;
float dataFloat;
};
Run Code Online (Sandbox Code Playgroud)
Python中有解包函数,将字符串解释为压缩二进制数据.但我在Scala中找不到任何类比.
在Scala中进行这种映射的标准方法是什么?逐个读取字节非常不合适.我需要解析的协议从20世纪80年代开始,包含不同的字段(short,int,float),因此逐字节读取它将是非常低效的.
我必须为具有以下规范的消息创建一个编解码器。消息长度由一个字节指示,该字节的最低有效位是扩展标志,当置位时表示必须使用以下(可选)字节作为最高有效位字节。(希望有道理)可以描述如下:
+ ------------------------------------------------- --------------------------------- + | 长度| | | + ---------------------------------- + ----- +-+ ------ --------------------------------- + | | | | | | Len1(LSB)| 分机| | Len2(MSB)-可选| + ---- + ---- + ---- + ---- + ---- + ---- + ---- + ----- + + ---- +- -+ ---- + ---- + ---- + ---- + ---- + ---- + | | | | | | | | | | | | | | | | | | | | …