编码与矢量不相邻的矢量长度字段

时间:2016-10-20 09:53:04

标签: scodec

我有以下结构我喜欢编码。 我知道如果size字段直接位于矢量数据前面,我可以使用vector()编码矢量。但是这里编码矢量大小的字段不相邻。

case class Item(
    address: Int,
    size: Int,
)
case class Header {
    // lots of other fields before
    numOfItems: Int,
    // lots of other fields after
}
case class Outer(
    hdr: Header,
    items: Vector[]
)

外部解码是可以的:

从位向量读取Header.numOfItems,并使用vectorOfN创建项目(提供(hdr.numOfItems,Item.codec))

外部编码是问题所在:

编码时我想从items.length中获取numOfItem。 我知道我可以在更新项目Vector时使用附加代码设置numOfItems,或者在编码回调"之前使用"之类的东西。

问题是,是否有更优雅的解决方案。对Header.numOfItems Outer.items.length来说,string myQuery= @"SELECT MAX(ASD.eventDateTime) AS second, R.resourceID,R.resourceLoginID,ASD.agentID FROM AgentStateDetail AS ASD INNER JOIN Resource AS R ON ASD.agentID = R.ResourceID WHERE ASD.eventDateTime >='" + DateTime.Today.ToString("yyyy-MM-dd h:mm:ss") + "'AND ASD.eventDateTime <='2016-10-18 23:59:59' GROUP BY R.ResourceID,R.resourceLoginID,ASD.agentID" 是多余的,所以理想情况下只有[xml]$xml = Get-Content 'C:\Makro-Test\quandata.xml' $xml.QUANDATASET.GROUPDATA.GROUP.SAMPLELISTDATA.SAMPLE | foreach { $_.id + ":" + $_.name + ":" + $_.COMPOUND.id + ":" + $_.COMPOUND.name + ":" + $_.COMPOUND.PEAK.analconc } 编码器应该知道numOfItems。

2 个答案:

答案 0 :(得分:3)

您可以尝试使用ActiveRecord::StatementInvalid - PG::SyntaxError: ERROR: syntax error at or near ")" LINE 1: ...media" WHERE "instagram_media"."instagram_account_id" IN () ^ : SELECT COUNT(*) FROM "instagram_media" WHERE "instagram_media"."instagram_account_id" IN (): 构建编解码器,并在不构建consume()对象的情况下启动:

Outer

如上所述,您在编码时会得到以下信息:case class OuterExpanded( fieldBefore: Int, // Field before number of items in the binary encoding fieldAdter: Int, // Field after number of items in the binary encoding items: Vector[Item] // Encoded items ) // Single Item codec def itemC: Codec[Item] = (int32 :: int32).as[Item] def outerExpandedC: Codec[OuterExpanded] = ( int32 :: // Field before count int32.consume( c => // Item count int32 :: // Field after count vectorOfN(provide(c), itemC)) // 'consume' (use and forget) the count (_.tail.head.length) // provide the length when encoding ).as[OuterExpanded] 返回

outerExpandedC.encode(OuterExpanded(-1, -1, Vector(Item(1,2), Item(3,4))))

之后,您可以Successful(BitVector(224 bits, 0xffffffff00000002fffffffe00000001000000020000000300000004)) ^ ^ ^ ^-------^-> First Item |-1 | |-2 |Vector length inserted between the two header fields xmap()将其他标题字段打包到自己的对象中。即(向Codec[OuterExpanded]Outer添加两种转换方法):

OuterExpanded

这可能适用于更复杂的情况,尽管我并不完全熟悉无形的情况。异构列表 - 或def outerC: Codec[Outer] = outerExpandedC.xmap(_.toOuter,_.expand) case class OuterExpanded(fieldBefore: Int, fieldAfter: Int, items: Vector[Item]) { def toOuter = Outer(Hdr(fieldBefore,fieldAfter), items) } case class Outer(header: Hdr, items: Vector[Item]) { def expand = OuterExpanded(header.beforeField1, header.beforeField1, items) } - 并且可能有更好的方法来获取向量的长度,而不是在上面的示例中调用HList,尤其是如果您在数字后面有多个字段编码值。

此外,Codec scaladoc是发现有用运算符的好地方

答案 1 :(得分:0)

根据之前的回答,我提出了类似下面代码的内容。 我使用上面的消费技巧形式和AtomicInteger来保持矢量的大小。

import java.util.concurrent.atomic.AtomicInteger
import scala.Vector
import org.scalatest._
import scodec._
import scodec.Attempt._
import scodec.codecs._
import scodec.bits._

object SomeStructure {
  case class Item(
    address: Int,
    size: Int)

  def itemC: Codec[Item] = (int32 :: int32).as[Item]

  case class Hdr(
    beforeField1: Int,
    // vectorSize would be here
    afterField1: Int)
  // vectorSize is an "in" param when encoding and an "out" param when decoding
  def hdrC(vectorSize: AtomicInteger): Codec[Hdr] =
    (int32 ::
      int32.consume(c => {
        vectorSize.set(c);
        int32
      })((i) => vectorSize.get)).as[Hdr]

  case class Outer(
    hdr: Hdr,
    var items: Vector[Item])

  def outerC() = {
    // when decoding the length is in this atomic integer
    // when encoding it is set before 
    val c = new AtomicInteger(-1)
    (hdrC(c) :: lazily(vectorOfN(provide(c.get), itemC)))
      .xmapc(identity)((g) => { c.set(g.tail.head.length); g })
  }.as[Outer]
}

import SomeStructure._
class SomeStructureSpec extends FlatSpec with Matchers {
  val bv = hex"ffffffff00000002ffffffff00000001000000020000000300000004".bits
  val v = Vector(Item(1, 2), Item(3, 4))
  val bv2 = hex"ffffffff00000003ffffffff000000010000000200000003000000040000000500000006".bits
  val v2 = Vector(Item(1, 2), Item(3, 4), Item(5, 6))
  val o = Outer(Hdr(-1, -1), v)

  "outerC" should "encode" in {
    o.items = v
    outerC.encode(o) shouldBe Successful(bv)
    o.items = v2
    outerC.encode(o) shouldBe Successful(bv2)
  }
  it should "decode" in {
    o.items = v
    outerC.decode(bv) shouldBe Successful(DecodeResult(o, BitVector.empty))
    o.items = v2
    outerC.decode(bv2) shouldBe Successful(DecodeResult(o, BitVector.empty))
  }
}