You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Construct框架RepeatUntil处理器使用疑问及非递增ID适配

问题:Construct框架处理非递增ID的二进制数组结构

在使用Construct框架处理二进制结构时,遇到如下场景:结构包含numResults(Int16ul)字段,以及对应数量的resultItems数组;每个resultItems由ID(不总是递增)、strLen、my_str[strLen]组成。已知需要使用RepeatUntil组件,但不清楚其重复处理器的工作逻辑,当前代码仅在ID递增时有效,求指导如何实现非递增ID下遍历所有resultItems。

原代码示例

import construct as ct
from pprint import pprint

def repeat_handler( x, lst, ctx):
    pprint(f'{x=}, {lst=}, {ctx=}')
    pprint(f'{ctx.numResults=}, {x["ID"]=}')
    return ctx.numResults==x["ID"]

format = ct.Struct(
    'numResults' / ct.Int16ul,
    'resultItem' / ct.RepeatUntil(repeat_handler,
                       ct.Struct(
                            'ID'     / ct.Int16ul,
                            'strLen' / ct.Int16ul,
                            'my_str'    / ct.PascalString(ct.Computed(ct.this.strLen) , 'ISO-8859-1'),
                       ),
          ),
)

测试代码

d = dict(numResults=2, resultItem=[ dict(ID=0, strLen=3, my_str='abc'),
                                    dict(ID=1, strLen=3, my_str='abc'),
                                    dict(ID=2, strLen=3, my_str='abc')]
)

f= format.build(d)
pprint(f)
pprint(format.parse(f))

解决方案

原代码的问题在于RepeatUntil的停止条件依赖ID与numResults相等,这仅在ID递增且连续的情况下有效。实际上RepeatUntil的处理器函数接收三个参数:

  • x:刚解析出的当前条目
  • lst:已经解析完成的所有条目组成的列表
  • ctx:解析上下文,包含已解析的numResults字段

正确的停止逻辑应该是判断已解析的条目数量是否达到numResults指定的值,也就是当len(lst)等于ctx.numResults时停止重复,这样完全不依赖ID的取值。

修改后的处理器函数

def repeat_handler(x, lst, ctx):
    return len(lst) == ctx.numResults

完整修改后代码

import construct as ct
from pprint import pprint

def repeat_handler(x, lst, ctx):
    # 已解析条目数等于指定数量时停止
    return len(lst) == ctx.numResults

format = ct.Struct(
    'numResults' / ct.Int16ul,
    'resultItem' / ct.RepeatUntil(
        repeat_handler,
        ct.Struct(
            'ID'     / ct.Int16ul,
            'strLen' / ct.Int16ul,
            'my_str' / ct.PascalString(ct.Computed(ct.this.strLen), 'ISO-8859-1'),
        ),
    ),
)

# 测试非递增ID场景
d = dict(
    numResults=2,
    resultItem=[
        dict(ID=5, strLen=3, my_str='abc'),
        dict(ID=2, strLen=3, my_str='def')
    ]
)

f = format.build(d)
pprint(f)
pprint(format.parse(f))

这样修改后,无论ID是任意值,只要numResults与实际条目数量匹配,就能正确解析出所有resultItem。

内容的提问来源于stack exchange,提问作者Startin Mohanzl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:50:22