简体   繁体   English

如何动态提供N个编解码器来处理不包含size字节的二进制字段记录的字段作为VectorCodec

[英]How to dynamically provide N codecs to process fields as a VectorCodec for a record of binary fields that do not contain size bytes

Considering this function in Decoder:考虑解码器中的这个函数:

  final def decodeCollect[F[_], A](dec: Decoder[A], limit: Option[Int])(buffer: BitVector)(implicit cbf: Factory[A, F[A]]): Attempt[DecodeResult[F[A]]] = {

What I really need is dec: Vector[Decoder[A]] , like this:我真正需要的是dec: Vector[Decoder[A]] ,像这样:

  final def decodeCollect[F[_], A](dec: Vector[Decoder[A]], limit: Option[Int])(buffer: BitVector)(implicit cbf: Factory[A, F[A]]): Attempt[DecodeResult[F[A]]] = {

to process a binary format that has fields that are not self describing.处理具有非自描述字段的二进制格式。 Early in the file are description records, and from these come field sizes that have to be applied later in data records.文件的早期是描述记录,来自这些记录的字段大小必须稍后应用到数据记录中。 So I want to build up a list of decoders and apply it N times, where N is the number of decoders.所以我想建立一个解码器列表并应用它 N 次,其中 N 是解码器的数量。

I could write a new function modeled on decodeCollect, but it takes an implicit Factory, so I probably would have to compile the scodec library and add it.我可以编写一个以 decodeCollect 为模型的新函数,但它需要一个隐式工厂,所以我可能必须编译编解码器库并添加它。

Is there a simpler approach using what exists in the scodec library?是否有使用编解码器库中存在的更简单的方法? Either a way to deal with the factory or a different approach?是处理工厂的方式还是不同的方法?

I finally hacked a solution in the codec codebase.我终于在编解码器代码库中破解了一个解决方案。 Now that that door is open, I'll add whatever I need until I succeed.现在那扇门是开着的,我会添加任何我需要的东西,直到我成功。

  final def decodeNCollect[F[_], A](dec: Vector[Decoder[A]])(buffer: BitVector)(implicit cbf: Factory[A, F[A]]): Attempt[DecodeResult[F[A]]] = {
    val bldr = cbf.newBuilder
    var remaining = buffer
    var count = 0
    val maxCount = dec.length
    var error: Option[Err] = None
    while (count < maxCount && remaining.nonEmpty) {
      dec(count).decode(remaining) match {
        case Attempt.Successful(DecodeResult(value, rest)) =>
          bldr += value
          count += 1
          remaining = rest
        case Attempt.Failure(err) =>
          error = Some(err.pushContext(count.toString))
          remaining = BitVector.empty
      }
    }
    Attempt.fromErrOption(error, DecodeResult(bldr.result, remaining))
  }

  final def encodeNSeq[A](encs: Vector[Encoder[A]])(seq: collection.immutable.Seq[A]): Attempt[BitVector] = {
    if (encs.length != seq.length)
      return Attempt.failure(Err("encodeNSeq: length of coders and items does not match"))
    val buf = new collection.mutable.ArrayBuffer[BitVector](seq.size)
    ((seq zip (0 until encs.length)): Seq[(A, Int)]) foreach { case (a, i) =>
      encs(i).encode(a) match {
        case Attempt.Successful(aa) => buf += aa
        case Attempt.Failure(err) => return Attempt.failure(err.pushContext(buf.size.toString))
      }
    }
    def merge(offset: Int, size: Int): BitVector = size match {
      case 0 => BitVector.empty
      case 1 => buf(offset)
      case n =>
        val half = size / 2
        merge(offset, half) ++ merge(offset + half, half + (if (size % 2 == 0) 0 else 1))
    }
    Attempt.successful(merge(0, buf.size))
  }


private[codecs] final class VectorNCodec[A](codecs: Vector[Codec[A]]) extends Codec[Vector[A]] {

  def sizeBound = SizeBound(0, Some(codecs.length.toLong))

  def encode(vector: Vector[A]) = Encoder.encodeNSeq(codecs)(vector)

  def decode(buffer: BitVector) =
    Decoder.decodeNCollect[Vector, A](codecs)(buffer)

  override def toString = s"vector($codecs)"

}

  def vectorOf[A](valueCodecs: Vector[Codec[A]]): Codec[Vector[A]] =
    provide(valueCodecs.length).
      flatZip { count => new VectorNCodec(valueCodecs) }.
      narrow[Vector[A]]({ case (cnt, xs) =>
        if (xs.size == cnt) Attempt.successful(xs)
        else Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
      }, xs => (xs.size, xs)).
      withToString(s"vectorOf($valueCodecs)")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM