拓冰建站拓冰建站
首页 / 资讯中心 / 正文

fq 开发路线图与已知缺陷全解析:从 doc/TODO.md 看 jq for binary formats 的演进方向

fq 开发路线图与已知缺陷全解析从 doc/TODO.md 看 jq for binary formats 的演进方向【免费下载链接】fqfq - jq for binary formats. Tool, language and decoders for working with binary formats.项目地址: https://gitcode.com/gh_mirrors/fq/fqfq 是一个面向二进制格式的 jq 式工具与语言用于解码、查询和转换各类二进制文件。本文以仓库内 doc/TODO.md 这份开发路线图文档为骨架系统梳理 fq 当前已知的缺陷Known bugs、CLI/REPL、语言、函数、解码引擎、格式解码器、测试、文档与 gojq 子项目层面的改进计划并逐一结合 pkg/interp、format 等目录下的源码实现展开印证。读完本文你将能理解 fq 内部各模块选项系统、REPL、解码引擎、格式注册的真实运作方式、已知的边界问题以及社区/贡献者可以切入的开发方向。一、这份 TODO 文档在仓库中的定位doc/TODO.md是 fq 项目的已知问题与未来构想清单全文分为两大部分Known bugs to fix17 条已经被确认、但尚未修复的缺陷覆盖解码正确性、REPL 交互、自动补全、选项作用域、性能等多个维度TODO and ideas按 CLI、CLI and REPL、Language、Functions、Tests、Documentation、Decode、Formats、Scripts、gojq、Big things 共 11 个子主题组织的功能规划粒度从一行配置改动到整个 Web 界面不等。它对应的开发指南是 doc/dev.md新增格式解码器的步骤、解码器 API 约定、测试与 fuzz 流程两者配合阅读可以还原 fq 从主干功能到细节打磨的完整演进脉络。本文聚焦 TODO 文档本身源码仅作为佐证。二、已知缺陷Known bugs to fix17 条未修复问题逐项解读TODO 文档的第一部分是已确认的 bug 清单。这些条目虽然短但每一条都指向具体的代码行为或交互边界下面逐条结合源码展开。2.1 十六进制切片后解码产生错误字节fq -n aabbccdd | hex | tobytes[1:] | decode(bytes) | tobytes得到二进制aabbcc而正确结果应为bbccdd。该命令的意图是把字符串aabbccdd按 hex 解码为 4 字节二进制丢弃首字节后剩余 3 字节应为bb cc dd但实际输出却是aabbcc丢弃的是尾部而非头部。TODO 作者推测是decode此处为 raw 解码被 root value 缓冲区搞混了。从实现看二进制值在 pkg/interp/decode.go 中被表示为带 lazy 求值的gojqx.Lazy值只有真正被消费如tobytes时才读取位范围因此基于位范围 根缓冲区的切片语义极易在嵌套派生值上出错。这与 2.10 中提到的array decode value[{start: ...: end: ...}]区间语法问题同源都属于解码值切片/区间这一底层设施不完善。2.2 Buffer 与字符串的二义性Buffers/string duality is confusing, most string functions should be wrapped to understand binary.fq 中二进制数据buffer与字符串在查询层并存但大多数字符串函数如length、split、正则相关等目前只能处理字符串而不能直接处理二进制 buffer。TODO 提出的方向是把大部分字符串函数包装成能理解二进制。这也是 pkg/interp/binary.jq 中tobits/tobytes体系unit、keep_range、pad_to_units参数需要与字符串函数协同的原因。2.3 REPL 取消时子 REPL 清理不彻底REPL cancel seems to sometimes exit a sub-REPL without properly cleanup options.fq 的 REPL 支持嵌套在表达式中通过| repl进入子 REPL见 pkg/interp/repl.jq 中_repl对_options_stack的 push/pop 管理。当用户在子 REPL 中按下取消ctrl-c时有时会直接退出子 REPL 而没有正确清理_options_stack导致选项状态泄漏到外层。与之相关的是 2.9 的ctrl-c 只能中断求值解释器无法中断父解释器的 display 输出以及 2.10 的ctxstack 索引取消顺序错误——这三条共同指向用户中断context cancel机制需要整体重构即 TODO 中单独列出的Rework cli/repl user interrupt (context cancel via ctrl-c)。2.4 值错误只能通过._error访问Value errors, can only be accessed with._error.当解码失败时fq 并不会抛出异常而是把错误信息挂在解码结果的._error字段上。从 pkg/interp/format_decode.jq 可以看到生成的from_format系列函数正是利用这一点做了失败即报错的封装def from_\(.key)($opts): decode(\(.key | tojson); $opts) | if ._error then error(._error.error) end;也就是说decode(mp3; {})返回的结果可能带._error而from_mp3会把._error转成真正的 jq 错误。错误的具体结构在 pkg/interp/decode.go 中通过valueError与decode.FormatsError组装包括多条格式候选解码失败时的vs数组。TODO 认为这种错误挂字段的方式不够直观未来可能引入更自然的错误通道。2.5tovalue({bits_format: ...})只作用于根值tovalue({bits_format: base64})only affect root value.bits_format决定二进制值以何种字符串形式呈现base64、hex、md5、byte_array、snippet、string、truncate 等。问题是tovalue传入的bits_format选项只对根值生效嵌套的二进制字段不受影响。完整的bits_format取值定义位于 pkg/interp/options.jq 的_opt_options中测试用例见 pkg/interp/testdata/binary.fqtest对test.mp3的audio_data依次尝试md5/hex/base64/snippet/byte_array等格式。相关的全局选项默认值也在 pkg/interp/options.jq 的_opt_build_default_fixed中定义选项默认值说明array_truncate50数组显示截断长度string_truncate50字符串显示截断长度addrbase/sizebase16 / 10地址、大小显示进制completion_timeout1秒REPL 补全等待超时decode_groupprobe默认解码格式组color随 TTY 与NO_COLOR自动判断是否输出颜色byte_colors三段式规则字节值的着色规则CSV 范围数组2.6 非全局变量的自动补全与scope失效Auto complete of non-global variables is broken.scopeis broken for variables.REPL 的自动补全实现在 pkg/interp/repl.jq 的_complete/_complete_scope中_complete_scope通过scope | map(split(/)[0]) | unique收集当前作用域内的定义名与 jq 关键字。但scope对局部变量如as $x引入的变量并不可靠导致$开头的变量补全失效补全实现里也留有# TODO: handle variables via ast walk?的注释说明作者认为正解应是从 AST 层面解析变量。相关的改进项还有 Auto complete $variables见 3.2。2.7 多 JSON 输入时jq与fq行为不一致echo {} {} {} | jqvsecho {} {} {} | fqworks differently. fq currently decodes one root format and might add unknown gap fields etc.jq 会把每行 JSON 当作独立输入逐个输出而 fq 默认把整个输入流交给probe组解码为单一根格式还可能为未知间隙自动添加gap字段。TODO 提出或许json格式应当特殊处理与 jq 的多输入语义对齐这与 pkg/interp/options.jq 中slurp、null_input、filenames等选项的解析逻辑相关。2.8format/0与 jq 内建format/1的命名冲突format/0overlap with jq builtinformat/1. What to rename it to?decode_format?fq 提供了一个 0 参数的format函数返回当前值的解码格式名而 jq 内建了format/1如x | format(%02d)这类字符串格式化。二者共存造成语义冲突TODO 提出的候选改名是decode_format。这属于命名层面的兼容性设计问题。2.9 REPL 中大量输出无法被中断repl expression returning a value that produced lots of output cant be interrupted. This is because ctrl-c currently only interrupts the eval interpreter, outputted value is printed (display) by parent interpreter.表达式求值eval与结果展示display在 REPL 中分属不同层级ctrl-c 能中断子解释器的求值但一旦进入父解释器的display输出阶段如打印.frames这种超大值中断就失效了。TODO 在 pkg/interp/repl.jq 的_repl_eval中已经尝试run display in sub eval so it can be interrupted把 display 放进子 eval 以便可中断但根本解决仍依赖整体 context cancel 重构。2.10 解码值区间切片语法损坏array decode value[{start: ...: end: ...}]syntax a bit broken.TODO 希望支持用对象形式对解码值取位区间切片[{start: ..., end: ...}]但当前实现有点坏。这与 2.1 的 hex 切片 bug 同属位范围切片问题也和 pkg/interp/query.jq 的查询语法解析相关。2.11 REPL 补全可能产生副作用REPL completion might have side effects. Make interp.Function type know and wrap somehow? input, inputs, open, ...补全过程会实际执行候选函数查询来推断返回值类型pkg/interp/repl.jq 的_query_index_or_key会对每个候选执行_eval($q; {})。像input、inputs、open这类有副作用的函数读取输入、打开文件被补全触发时会消费输入或泄漏文件句柄。TODO 的设想是让interp.Function类型知道自己是否有副作用并加以包装防护——这与后续 3.4 中open何时关闭文件、open泄漏、安全模式解释器、自动补全中是否允许open等条目是一组问题。2.12 group 参数机制需要重做Rework group arguments so that{is_probe:true}is not needed. Look up group name and see if it has an argument somehow?probe是 fq 内置的解码格式组用于自动探测输入属于哪种格式。当前探测行为依赖在选项中传递{is_probe:true}之类的内部标志对应 pkg/interp/options.jq 中decode_group选项的 probe 默认值TODO 希望改成根据 group 名自动判断是否带参数的声明式方式去掉显式内部标志。2.13Interp.Options性能问题OptimizeInterp.Optionscalls, now called per display. Cache per eval? needs to handle nested evals.Interp.Options目前每次display都会被调用涉及_options_stack的合并计算见 pkg/interp/options.jq 的options函数它把stdout尺寸、选项栈与显式 opts 做add合并。TODO 建议按 eval 缓存但需处理嵌套 eval 的上下文切换。三、CLI 与 REPL 改进计划TODO 的第二大部分是对各子系统的功能构想其中 CLI/REPL 相关的条目密度最高。3.1 CLIReset color at promptcontext cancel提示符处重置终端颜色结合 context cancel 一起处理避免中断后终端颜色状态脏掉。相关实现位于 pkg/interp/repl.jq 的_prompt通过_ansi_if与options中的colors方案上色。3.2 CLI 与 REPLctxstack index cancel 顺序错误应改为跳过中断发生时上下文栈的索引清理顺序不正确TODO 认为更合理的做法是直接跳过而非逐层取消。Pager分页器支持长输出希望引入$PAGER或某种显式语法如.. | less来分页浏览长输出。这对应dump输出超大根值时如.frames的体验问题。dump大根值输出不可取消与 2.9 同一根源dump由父 REPL 执行无法被 ctrl-c 中断。错误位置^指针编译错误时在输入行下方用^标注出错列。实际上 pkg/interp/repl.jq 的_repl_on_compile_error已经实现了这个功能含 unicode 模式下的⬆箭头TODO 条目属于当时的规划如今已有雏形。可配置的历史文件名REPL 历史记录文件目前未提供配置入口。补全$variables支持$变量的自动补全与 2.6 的 scope 问题相关。补全需要转义的 key对需要引号转义的字段名目前直接过滤掉希望补全时能自动加引号改写前面的输入。补全对象时自动追加.当候选唯一且是对象时自动补全一个.以提示继续下钻pkg/interp/repl.jq 的_query_index_or_key已据此返回.或[]。支持JQ_COLORS且扩展为name形式fq 已有自己的colors选项null、false、number、string、objectkey、error、dumpheader、prompt_repl_level等键见 pkg/interp/options.jq希望兼容 jq 的JQ_COLORS环境变量并扩展出按值类型/语义命名的配色方式。四、语言与函数层规划4.1 语言层面清理/让二进制 buffer 语义自洽与 2.2 呼应需要从语言层统一 buffer 与字符串的表示与操作。gojq 用 golangint作切片索引非 64 位 CPU 上可能出问题这与 gojq 子项目的移植深度有关属于架构层备注。4.2 函数层面buffer 截断、左右填充希望新增 buffer 的truncate、左/右pad类函数。toimage终端内联图片可以用 CLI 输出\x1b]1337iTerm2 的 inline image 协议实现但 TODO 认为也许更适合做成 UI 功能。toplot终端内绘图类似toimage的可视化构想。dump支持二进制、列代码通用化希望dump、hexdump可能还有bindump共享同一套列渲染代码且能处理二进制数据。dump对行范围不连续处着色/提示当输出覆盖的位范围有跳跃时给出视觉提示。hexdump等处理非字节对齐数据当前hexdump假定字节对齐需要支持 1 字节以内的位宽数据。重做 cipher 函数接口TODO 给出了两种候选风格——ctr(aes(key), iv)或cipher(ctr(iv), aes(key))即算法/模式/参数如何组合的 API 设计问题。open何时关闭文件、open的泄漏问题文件与 ctxreadseeker打开的文件句柄与可取消读取器需要明确的生命周期管理对应internal/ctxreadseeker、internal/aheadreadseeker等 IO 栈组件。安全模式解释器设想一个禁止open等危险操作的沙箱化解释器同时配套自动补全中是否允许open的策略见 2.11。摘要树summary tree按格式输出各部分的摘要统计样本数量等。以紧凑形式列出所有唯一路径便于快速浏览二进制结构中所有可达的查询路径。五、测试与文档规划5.1 测试update测试不保留readlines的注释顺序-update模式重写期望输出时注释会被打乱相关测试框架见 pkg/fqtest。空文件测试需要覆盖空输入文件的解码/错误行为。CLI 测试raw 输出写入、颜色输出等端到端用例。交互式测试REPL 等交互场景的自动化测试仓库中已有pkg/cli/test_repl.exp、test_cli_ctrlc.exp、test_cli_ctrld.exp等 expect 脚本作为基础。5.2 文档help(topic)函数在 REPL 内通过 jq 函数调用的形式查看帮助fq 的 CLI 帮助系统见 doc/fq.1.tmpl.adoc格式帮助则通过//go:embed嵌入各format/*/*.md。从源码生成文档用make doc生成 README 与 man page需要 FFmpeg 与 Graphviz见 doc/dev.md 与 Makefile。-n、inputs/0、input/0行为文档化与 jq 保持一致相关选项定义见 pkg/interp/options.jq 的null_input、filenames。提及empty.somethingjq 的empty与字段访问组合的边界行为。采用 JQ-Distilled 的记号法TODO 引用了一个 jq 教学文档的表示风格来规范 fq 的 jq 相关文档写法。带交互示例的手册README 中已有交互式示例如./fq命令与demo.svgTODO 希望手册级文档也配套可交互示例。六、解码引擎Decode重构方向TODO 中解码引擎层面的规划最能反映 fq 的架构演进思路用接口节省内存设想引入Value V接口使 U、Str 等类型有各自的实现替代当前统一的对象模型。当前值模型是scalar.S*decode.Compound见 doc/dev.md 的 Decoder API 一节TODO 认为可以更省内存。装饰sym、显示格式数组化符号值sym与显示格式目前以字段形式挂在值上希望改为数组式的装饰列表便于扩展。保存原始文件名目前只在 description 字段中粗略记录来源。更合理的合成值synthetic values当前合成值长度为 0语义不完整。清理并重想嵌套 bufferzip、ogg 这类 muxed 格式嵌套缓冲区的读取与共享是格式组合的基础设施。大小端位域辅助elf 等为按位域解析的格式如 ELF提供统一的大小端位域读取助手。清理校验和机制TODO 希望校验和直接作为普通字段并在不匹配时输出 warning 而不是失败。用 jq 写解码器设想直接用 jq 的数组/对象语法编写解码器传递解码上下文、收集字段并构建树。目前format_decode.jq只生成decode/from_format的调用封装真正的解码器仍是 Go 代码。控制/限制嵌套解码深度如probe({depth:1})或按格式跳过解码用于处理超大文件的部分解码。解码过程中无法使用 range由于解码时范围尚未计算完成range查询在解码进行中不可用。跟踪值的编码信息为每个值记录其编码u16le、utf8、varint等便于展示与再编码。可选忽略范围检查提供解码到读取错误为止的模式例如截断的 mp4mdat也能尽力解码而不是失败。七、格式解码器Formats扩展清单TODO 列出了待新增/改进的具体格式新增解码器asn1_ber/asn1_der/asn1_cerASN.1 目前已有 format/asn1/asn1_ber.goDER/CER 是后续拆分、flatbuffer、capnproto、dsf。格式参数传递支持向格式解码器传递参数。jq 中的值解码器如u(32)、u32在查询层直接按数值类型解码片段。warning 与 error 体系为mp4sample counts、flac截断的 picture、混用采样率/位深等增加一致性校验告警。protobufschema 支持、matroskacrc、mp4styp segment 测试。格式成熟度文档化为每个格式标注成熟度/完整度。json格式规范化TODO 直言json is a bit of a special case now与 2.7 的多输入问题相关。exif in mp4heif/heicTODO 给出了一个完整的端到端示例查询展示了 fq 如何组合grep、parent、select、tobytes区间切片与exif解码器. as $r | grep(iloc) | parent.items[] | select(.id (first($r | grep(exif;i)) | parent.id)).extends[0] as $e | $r | tobytes[$e.offset10:$e.offset$e.length] | exif该查询先从ilocbox 中定位exif数据项grep(exif;i)为大小写不敏感搜索grep实现在 pkg/interp/grep.jq再通过tobytes按偏移与长度切出 EXIF 字节流交给exif解码器。这也是 pkg/interp/binary.jq 中tobytesunit: 8、pad_to_units: 0的实际用法范例。八、脚本Scripts与 gojq 子项目8.1 脚本层基于常见字段名的探测工具probe之外提供按常见字段名猜格式的辅助脚本。MIME codec 编解码器支持avc1.PPCCLL这类 RFC 6381 风格的 MIME 编码器/解码器字符串。针对 mp4、matroska 的校验脚本用 fq 语言本身编写格式验证脚本。8.2 gojq 子项目fq 使用的 gojq forkgithub.com/wader/gojq的fq分支相关的 TODO 包括常见错误在本地重新实现TODO 注明 Common errors with gojq? re-implemented now即部分错误处理已改为在 fq 内自行实现。0b字面量问题0b在 bin/hex/... 字面量变更后出现1.7976931348623157e308之类的异常值属于 gojq fork 的数值字面量解析回归。仿照 gojq 的builtin.go做提速把常用内建函数做成本地实现以提升性能。移除scopedump清理调试用的作用域转储函数。九、更大愿景Big thingsTODO 的最后一部分是偏长期的产品形态构想fq play 网站在线演示/练习站点。UI/Web 界面树形界面、多 REPL 窗口、在 hex 视图中更优雅地展示重叠字段。Jupyter notebook 集成让 fq 成为 notebook 中的内嵌工具。FUSE 接口把二进制文件挂载成文件系统通过目录/文件访问其结构。懒解码Lazy decode对已知大小的结构延迟解码既能提升性能也能节省内存可通过重新解码替代。十、对使用者与贡献者的意义doc/TODO.md不仅是开发者的待办清单对 fq 用户也有实际参考价值规避已知边界上述 2.1hex 切片、2.4._error访问错误、2.5bits_format仅作用根值、2.7多输入行为差异等问题意味着在使用对应功能时要留意行为与直觉不符之处。理解选项与 REPL 机制pkg/interp/options.jq 集中定义了全部可配置项-o namevaluepkg/interp/repl.jq 展示了 REPL 的补全、提示符、slurp/spew等交互设计。贡献切入点清晰TODO 条目大多有明确验收标准如tobytes[1:]后应为bbccdd、format/0改名配合 doc/dev.md 中的新增格式步骤创建format/name目录、注册到 format/format.go 与 format/all/all.go、生成testdata/*.fqtest、make lint与make fuzz GROUPname可以快速上手提交修复或新格式。总的来说doc/TODO.md呈现了一个仍在快速演进中的二进制解析工具核心解码与查询能力已经成型但 buffer 语义、REPL 交互、中断模型与嵌套解码等深水区仍在持续打磨而格式解码器生态的扩展DER/CER、flatbuffer、capnproto、dsf则预示着 fq 的适用范围还在不断拓宽。【免费下载链接】fqfq - jq for binary formats. Tool, language and decoders for working with binary formats.项目地址: https://gitcode.com/gh_mirrors/fq/fq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门