fast_qr_moonbit

    Fast QR code generator library written in MoonBit

    qr
    qrcode
    fast-qr
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    7 days ago
    Downloads
    6

    #TryAndRun-TvT/fast_qr_moonbit

    基于 MoonBit 的高性能二维码(QR Code)生成库。 纯 MoonBit 实现、无外部依赖,逐位对齐 Rust 参考库 fast_qr v0.14.0

    项目状态:功能对齐收口(M0–M3 里程碑 ✅),moon test 全绿(146 个用例,含快照),仅 wasm-gc 后端回归通过。

    示例二维码(内容 https://example.com/,由 SvgBuilder 生成、SVG 矢量,缩放不失真):

    复跑(终端字符画 + SVG 打印):moon run cmd/main

    语言MoonBitwasm-gc;边界见「能力与局限」)
    标准ISO/IEC 18004 二维码(版本 1–40,ECL L/M/Q/H,8 掩码评分择优)
    许可Apache-2.0
    参考Rust fast_qr v0.14.0 逐位移植对齐


    #目录


    #功能特性

    • 纯 MoonBit 实现,无外部依赖,可直接 moon add 依赖到你的项目。
    • 标准合规:遵循 ISO/IEC 18004 —— 版本 V01–V40、四种纠错级别(L/M/Q/H)、 三模式自动编码(Numeric / Alphanumeric / Byte)+ 自动回退、8 种掩码评分择优。
    • 逐字节对齐参考:矩阵与 fast_qr v0.14.0 全量快照逐位一致,可解码读回原文。
    • 单后端产物:仅 wasm-gc(体积小、性能好;宿主需支持 GC 提案)。
    • 两用接口:过程式 QRCode::build 编排入口 + 链式 QRBuilder 便捷构造器。
    • 多样输出:终端字符画(to_str/print)与 SVG 字符串(SvgBuilder,6 种模块形状)。

    #能力与局限

    能力说明
    编码内容字节(ASCII) 输入;自动选择 Numeric / Alphanumeric / Byte,也可强制指定模式
    版本/纠错自动最小适配或强制指定版本 V01–V40;ECL 缺省 Quartile(Q),可显式 L/M/Q/H
    掩码自动 8 轮评分择优,或指定固定掩码(走快速路径)
    输出终端 Unicode 字符画、SVG 字符串

    已知局限(诚实声明):

    • 编码模式仅支持 Byte/Alphanumeric/Numeric;Kanji 模式暂不支持(与参考 fast_qr 一致)。
    • 输入按 ASCII 字节 处理(非 ASCII 多字节字符的语义见 S6 评审记录 的优化建议)。
    • 产物形态面向 wasm:MoonBit Int 32 位、纠错位流 KEEP_LAST=33(取 Rust wasm32 分支), 对真实 QR 语义无差别(详见 S9 评估记录 §2.4)。
    • 仅支持 wasm-gcmoon.mod 声明 supported_targets = "+wasm-gc",下游 native/JS 消费者会被构建系统 直接拒绝(实测 does not support target backend 'native')。库本身是纯 MoonBit,此为有意的分发范围收缩 其中 native 另需系统 C 编译器(当前 CI/本地镜像未装)。
    • 宿主需支持 wasm-gc(GC 提案):如 Node ≥ 22 / V8、启用 GC 的 wasmtime;CLI println 依赖 spectest.print_char 导入(非标准 WASI)。wasm(WASI) 通用兜底已移除,宿主接入面相应变窄。 取舍与复核见 S9n wasm-gc 收敛审计 §1。


    #快速开始

    在项目根目录(moon.mod 所在处)添加本库为依赖:

    # 需本模块已发布至 mooncakes;发布前的过渡期为 clone 本仓库按「从源码构建」体验 moon add TryAndRun-TvT/fast_qr_moonbit

    发布状态:尚未发布(0.1.0 待发布)。发布流程、元数据/命名核验、归档面治理 与发布前门禁清单见 mooncakes-发布方案.md 发布动作已脚本化:bash scripts/publish.sh(默认干跑,--publish 真发), 模块名迁移记录见 模块名迁移与发布链路核验.md

    moon.pkg 中声明依赖并起别名(本库包路径为 .../lib,别名默认即目录名 lib):

    import { "TryAndRun-TvT/fast_qr_moonbit/lib", }

    然后即可用 QRBuilder 生成二维码(链式设置纠错/版本/掩码):

    /// 由字符串输入构建 QRCode(缺省全部自动:mode 自动、ECL=Q、version 最小、mask 择优)。
    fn gen() -> @lib.QRCode {
    match @lib.QRBuilder::from_string("https://example.com/").build() {
    Ok(q) => q
    Err(_) => abort("content too large")
    }
    }

    fn main {
    let qr = gen()
    // 输出终端 Unicode 半块字符画(含边距)
    println(qr.to_str())
    // 输出 SVG 字符串(默认黑色方块 + 白色背景、margin=4),链式定制颜色与模块形状
    let svg = @lib.SvgBuilder::default()
    .module_color("#0000ff")
    .background_color("#ffffff")
    .shape(@lib.Shape::RoundedSquare)
    .to_str(qr)
    println(svg[:200].to_owned() + "...")
    }

    上述示例已在本仓库实测通过(moon check / moon run,wasm-gc)。

    主要公共类型一览(完整说明见 文档索引 各实现方案/记录):

    类型位置/说明
    ECL / Version / Mode / Mask纠错级别(L/M/Q/H)、版本(V01–V40)、编码模式、掩码枚举
    QRCode生成结果容器(矩阵 + size/version/ecl/mask/mode 元数据 + to_str/print
    QRCode::build / build_fixed过程式编排入口(input/mode/ecl/version/mask → Result[QRCode]buildSome(mask) 分支委托 build_fixed
    QRCode::empty空矩阵构造(宿主自建/改写矩阵的唯一入口,见下「矩阵读写」)
    QRCode::get / set / meta / data(+ size/version/ecl/mask/mode逐格读写与元数据访问器(set 不可变式,返回新 QRCode
    QRCode::select_capacity容量/版本三元组解析(显式模式参与判定,供自定义编排复用)
    QRBuilder链式构造器:from_string/new + mode/ecl/version/mask + build
    Module / ModuleType单像素模块(明暗 + 8 种功能归属);Module::new(value, type) 为通用构造
    SvgBuilder / ShapeSVG 字符串输出;6 种模块形状(square/circle/rounded_square/vertical/horizontal/diamond);链式 margin/module_color/background_color/shape
    Shape::from_name由名字(大小写不敏感)取形状枚举,未知名回退
    ECL::to_char纠错级别 → 显示字符(L/M/Q/H
    QRCodeError构造错误(EncodedData 数据过大、SpecifiedVersion 版本过小)

    #矩阵读写与自建(宿主可拿到 QRCode

    QRCode::build / QRBuilder::build 返回的就是 QRCodepub(all) struct), 宿主可直接读/改矩阵并交给输出层;从零自建则用 QRCode::empty(version) 拿一张干净画布:

    // ① 已有编码结果:读/改单格(set 为不可变式,返回新 QRCode,不改源)
    let (v, ecl, mask, mode) = qr.meta() // 元数据快照
    let dark = qr.get(0, 0).value() // 逐格读
    let qr2 = qr.set(0, 0, @lib.Module::new(true, @lib.ModuleType::Data)) // 逐格写

    // ② 从零自建:空矩阵(全亮)作起点,逐格写入后输出
    let canvas = @lib.QRCode::empty(@lib.Version::V05) // 边长 = 版本*4+17
    let drawn = canvas.set(10, 10, @lib.Module::new(true, @lib.ModuleType::Data))
    println(drawn.to_str())

    命名/形状等辅助入口:Shape::from_name("circle")(按名取形状)、 ECL::to_char(ECL::Q)(级别显示字符)、SvgBuilder::default().module_color(...)(链式配色)。


    #从源码构建

    先安装 MoonBit 工具链:

    curl -fsSL https://cli.moonbitlang.cn/install/unix.sh | bash export PATH="$HOME/.moon/bin:$PATH"

    模块根不设包(core 式布局):库包在 lib/,CLI 在 cmd/main/,构建需显式给包名。

    moon build lib # 编译库包 moon build cmd/main # 编译 CLI moon run cmd/main # 运行 CLI 演示(终端字符画 + SVG) moon test # 运行单元/快照测试

    提交前本地收尾检查(对齐 CI 门禁):

    export PATH="$HOME/.moon/bin:$PATH" moon fmt && moon info && moon check --deny-warn && moon test moon build lib --target wasm-gc --release moon build cmd/main --target wasm-gc --release moon test --target wasm-gc


    #编译为 Wasm

    唯一后端 wasm-gcmoon.modpreferred_target/supported_targets;边界见「能力与局限」)。

    # 唯一后端 wasm-gc(体积最小、性能最优,宿主只需提供 spectest.print_char) moon build cmd/main --release moon run cmd/main

    产物体积(release;复跑 bash scripts/bench-size.sh,完整口径见 S9i):

    产物后端raw-Oz(可加载档)
    cmd/qr-min(纯库调用 = 库实际体积)wasm-gc41427 B(40.5 KiB)31365 B(30.6 KiB)
    cmd/bench(基准外壳:argv/迭代/--dumpwasm-gc48038 B(46.9 KiB)36174 B(35.3 KiB)
    cmd/main(CLI:字符画 + SVG)wasm-gc44424 B(43.4 KiB)33593 B

    引用规范cmd/bench / cmd/main 是「命令形态」产物,外壳不随库分发, 不能代表库被宿主嵌入时的实际体积——引用库体积请用 cmd/qr-min 口径并注明后端与优化档。 体积金字塔wasm-gc-Oz):运行时地板(一行 println263 B → QR 核心净增 +31102 Bcmd/qr-min)→ 输出层(终端画 + SVG)+2228 Bcmd/main)→ 基准外壳 +4809 Bcmd/bench)。

    # -Oz 体积最优档(默认后端 wasm-gc): # --all-features 会开 custom-descriptors(RTT),其 exact heap type 在 Node/moonrun 上编译不过; # --disable-custom-descriptors 才产出「可被真实宿主加载」的最优档。 moon-wasm-opt _build/wasm-gc/release/build/cmd/main/main.wasm \ --all-features --disable-custom-descriptors -Oz -o main.min.wasm # 33593 B

    与 fast_qr 的体积对比(库对库主口径):两侧同为「核心-only + 一行 println (MoonBit cmd/qr-min vs fast_qr 无胶水裸探针):

    口径(B)MoonBit wasm-gcfast_qr 裸探针ours / fast
    raw41427594400.70×
    -Oz(可加载档)31365456870.69×
    核心净增(扣 hello 地板 263 / 20052 B)+31102+256351.21×

    结论:库对库,wasm-gc 在 raw 与 -Oz 两档都约 0.69–0.70×;扣掉运行时地板后核心净增 1.21×——差距大头是两侧运行时地板wasm-gc 263 B vs Rust 20052 B,76×),非 QR 实现差异。 命令形态(cmd/bench 含 argv/迭代外壳)对照与其他档位明细见 S9i · S9f


    #性能与体积

    引用的性能数字仅作选型与迭代基线,不代表对 fast_qr 的追赶承诺;逐条口径见 S9 系列文档。

    复跑入口:bash scripts/bench-host.sh宿主调用面:JS 反复带参调 wasm)· bash scripts/bench-host-var.sh统计稳定性:同一产物重复测量,给 CV / 单跑失稳率 / 漂移判定)· bash scripts/bench-layer2.sh(层② vs fast_qr)· bash scripts/bench.sh(层① 后端基准)· bash scripts/bench-size.sh(体积)。口径:输入 https://example.com/=20B、ECL H、强制 V03/V10/V40、 mask 自动择优;数字均为同 run 多轮取最小。核心结论:

    对比结果出处
    ① vs Rust fast_qr-wasm32(默认后端 wasm-gc单次 build 慢 ≈1.3–2.5×,逐位对齐 sha256 零差异;差距集中在 8 轮掩码择优主循环明细见下表 · S9p · S9j
    ② vs moonbit 生态 moonqr(同宿主、完整实现可比子集)本仓库全程快 2.5–4.1×(V03H 0.318 vs 0.805、V40H 9.46 vs 38.29 ms/单次,历史口径)S9d
    ③ 产物体积 vs fast_qrwasm-gc 各口径均更小(对称锚点 0.69×对照表见 编译为 Wasm · S9i

    ① 的数据随本轮 P0/P2/P2b 优化已刷新(2026-09-12 重测);② 为优化前(2026-09-06)历史口径, 未随本轮重测,量级参考即可。

    #① vs fast_qr-wasm32:性能明细

    主口径 = 宿主调用面(S9p 宿主一次 compile + 一次 Instance,随后在同一实例上反复把 JS 参数传给 wasm cmd/host-probe 导出 qr_generate(content: String, version: Int) -> Int,走 JS String Builtins stringref)——这才是宿主嵌入 wasm 库的真实形态,与 fast_qr qr_with 调用形态对称。 MoonBit 侧 = wasm-gc(默认后端、实际分发形态),两侧逐位对齐 sha256 零差异:

    模块数本仓库 MoonBit(wasm-gc)fast_qr-wasm32fast / ours每模块成本 ours / fast
    V03H8410.213 ms0.087 ms0.407×(慢 ≈2.5×)0.253 / 0.103 µs
    V10H32490.643 ms0.399 ms0.620×(慢 ≈1.6×)0.198 / 0.123 µs
    V40H313294.659 ms3.523 ms0.756×(慢 ≈1.3×)0.149 / 0.112 µs

    旧命令形态口径cmd/bench,保留作对照):A 每次新建 Instance (与 fast_qr「一次调用」同形,会系统性夸大差距)fast/ours = 0.263 / 0.528 / 0.728×; B 单实例摊薄 = 0.340 / 0.574 / 0.737×。三者对照见 S9p §4.1。 护栏全绿:宿主面 checksum 与 cmd/bench <点> 1 逐点相同(41/81/230,证明两个口径 是同一计算)· 同实例重复调用结果恒定 · 逐位对齐 sha256 三点相同 · Node shim vs moonrun 跨宿主一致。 统计口径(S9q:上表上行为「R=5 中位数」口径(R=3 回退取最小并与离散成对报出)。 同一产物重复测量(15 轮 × 5 次)的比值 CV:V03H 5.98% ≫ V10H 3.54% > V40H 0.35%—— 单次 build 越便宜,相对统计误差越大(固定项占比);V03H 单轮最坏可偏离真值 +17.3% 噪声非白噪声(lag-1 自相关 r1 = 0.28~0.68,存在热/频漂移),故同一进程内加轮次收益有限 更大偏差来自宿主调度态(6 线程满载竞争使三点一致慢 1.43–1.50×)与 Node 大版本(v22→v24 两侧共模 1.12–1.23×)。 纪律:只用「同 run 内成对比值」,不跨 run 加减绝对毫秒;主数取中位数而非算术平均(分布右偏)。 绝对毫秒数绑定测量环境(本表 Node v24.21.0 + 2026-09-14 宿主):跨环境只比「同 run 成对比值」, 方向性结论全环境成立,归因见 S9h 生态另两个 QR 包(qrc/moonbitqrcode)缺完整择优/Format 等,不可同口径对齐,仅参考口径见 S9d。

    #后续优化 Roadmap

    成本分解S9k,进程级差分实测):V40H 单次 auto 约 68% 在 8 轮 score(N1+N3 行/列 ≈37%、N2 ≈16%、N4 ≈15%)+ 11% apply_mask V03H 约 44% 在结果容器 wrap_packed(固定 31329 槽 + 逐格 Array[Module] 对象),8 轮评分仅 ≈28%。 优化优先级据此为 P0 wrap/容器(利小版本)+ P1 score 减趟/掩码特化(利大版本)

    参考库杠杆S9l 受控实验):fast_qr 的 掩码特化 实测 4–5.8×容器逐格对象税 ≈10×字节+切片评分 仅 ≈1.26×—— 即最大杠杆是掩码与容器,介质宽度本身有限。容器专项另评估官方查找表类型 ReadOnlyArray S9m):它是 FixedArray 的零成本封装、适合只读字面量表, 救不了 score/wrap 两大瓶颈。

    已落地(2026-09-12,明细见 S9n §6): P0 掩码特化 + P2 评分去闭包/列缓冲 + P2b N4 并入行趟——受控 A/B(cmd/bench 边际口径, 非上表层② 口径) V40H 单次 auto 5.97→4.42 ms(−26%)、V10H −24%、V03H −4% TOTAL_CHECKSUM 三项与基线完全相同(输出逐位不变,当次 moon test 全绿)。 上表层② 重测值(V40H 4.808 ms)与本段的 cmd/bench 边际值(4.42 ms)口径/宿主不同、不可直接对撞 ReadOnlyArray(T-R1/T-R2/T-R4)亦已落地:RS/常量查找表 与局部只读字面量全部只读化、moon.mod 启用 prefer_readonly_array lint 防回归——受控探针复验 division ≈1.30–1.34×(真实块长,两态 checksum 逐位一致),整 build ≈0.9% (分辨率边缘;定性「类型对齐为主、非性能杠杆」,见 S9n §6.6)。

    待做与上限:容器 P1 受阻于 QRCode.data 固定容量公共契约(须 API 评审);P2b(N2)/P3/T-R5 待做。 理论上限 ≈ fast_qr-wasm32 同执行模型数字(本环境层② V40 ≈3.55 ms):按 S9l 叠加方案 V40 现实仍可 收窄到 ≈3.6–4.2 ms(fast/ours 0.74×→≈0.84–0.98×,乐观逼近);V03 因每次 build 固定成本约束, 上界 ≈0.09–0.11 ms(fast/ours 0.37×→≈0.75–0.95×,仍慢约 1.1–1.4×、大概率不追平)。 历史路线与已否决项(T1/O1-a 就地翻转)见 S9b 统一优先级清单见 S9n §3


    #测试

    现状moon test 146 个用例全绿(含 wasm-gc 回归),26 个测试文件按「就近式三载体」分层 *_test.mbt 黑盒 / *_wbtest.mbt 白盒 / 源码内联 test {} 目前未使用): 用例数与文件数以实跑为准moon test / find lib cmd -name '*_test.mbt' -o -name '*_wbtest.mbt' | wc -l), 避免文档数字与实现漂移(详见 S11 §10.4)。

    覆盖
    黑盒公共枚举与 select_capacity 四态 + 模式/版本语义回归(4 条,v5)QRBuilder 链式等价、择优 mask 号回归(T2-d)、SVG 全串、终端画、21 个端到端全矩阵 hex 快照、11 条固化解码向量(T3-c)
    白盒位流、常量表交叉不变量 + 全表值级校验(T1-f)生成多项式独立推导(T1-a)、三模式编码、GF(256) 交织 + 黄金余数/交织向量(T1-c/T1-d)+ 交叉独立证据(T1-e)逐行/逐列打分明细(T2-a/T2-b)+ 结算边界(T2-b2/b3)、8 种掩码、放置逐格坐标(T2-c)Format 双副本布局(T2-e)独立数字真值(T0-c)属性测试四则(T4-a)枚举全量回环(T5-b)
    黄金值来源参考 fast_qr commit 53e8c99 侧由脚本产出(禁止手抄):snapshot_gen_s6.rs(全矩阵)、snapshot_gen_tables.py(常量表全表指纹)、snapshot_gen_rs_vectors.rs(division/structure)、snapshot_gen_score.rs(打分明细)、snapshot_gen_placement.rs(放置坐标)、snapshot_gen_default.py(Python qrcode 独立真值);一键校验 bash scripts/gen-goldens.sh --verify(四项零差异)

    测试完善路线S10-测试用例设计与完善roadmap.md测试维护入口)。 该路线已实跑三项验证,结论比「覆盖更多代码」更有信息量:

    • 强负向对照(变异检测):就地植入 21 类最小缺陷 → 21 类全部被现有测试检出 (复跑 bash scripts/test-audit.sh mutation)。历次审计共发现 4 条真漏检,全部已修: ① 容量表改中间项、② Format 表改非抽查 (ECL,mask)(初版,由 T1-f/T2-e 修复); N1 结算阈值 5→6(「恰好 5 连后立刻变色」路径无覆盖,由 T2-b2/b3 修复); 择优并列 s < bests <= best(并列规则是文档契约却无用例,由 T2-d2 修复)。 这两条首跑即漏检,是本轮审计最大的价值——分支存在 ≠ 分支被测契约必须显式锁定
    • 独立第三方解码回读:用纯 JS 解码器 jsqr 对矩阵做像素化解码, ① 三基准点(V03H/V10H/V40H)全部读回原文 T3-d 全语料 54 组(三模式 × 4 ECL × 4 版本 + 6 组自动版本靶点)全部读回原文 --mutate 负向对照组(破坏定位图案)全部解码失败——证明该证据链「能红、可信」 (入口 bash scripts/test-audit.sh decode,口径与标定见 S10 附录 D)。
    • ⚠️ 测试基础设施抓到了一条真 bug(v5):T3-d 探针首跑即暴露 QRCode::select_capacity模式语义缺陷——显式 mode 未参与容量判定, 较长 Alphanumeric/Byte 输入被静默按 Numeric 选版本,数据区装不下实际位流 矩阵不可解码(旧实现下 4/54 组 jsQR 返回 NULL)。 修复后与参考在 83,160 组参数上零差异;详见 S10c-select_capacity模式语义缺陷-定位与修复.md
    • 证据链钉版可复现:所有「与参考逐位一致」的黄金值均可由 scripts/gen-goldens.sh 在钉版参考上重建/校验(--verify 四项零差异),并已实测检出「中间项改值」「布局偏移」「系数改值」类缺陷。
    • 差分门禁scripts/diff-gate.shT4-c,本地/按需;已并入 gates.sh),把「与参考 wasm 逐位 sha256」 从仅打印升级为门禁;无参考制品时显式打印 skipped,避免静默假绿。
    • 覆盖率bash scripts/coverage.shT5-a 报告,见 S10b); --floorT5-b「不下降」门禁lib/** 未覆盖行 ≤ S10b 顶部 coverage-floor 标记)。 不设绝对百分比阈值——覆盖率是变异检测的补充而非替代(铁律 3),绝对阈值会诱发造无信息量用例。
    • 文档互链死链检查bash scripts/docs-link-check.shT6-c,本地/按需;已并入 gates.sh); 检查受版本控制 Markdown 的相对链接存在性(跳过外链/锚点、忽略代码块),当前 487 条零死链
    • 测试规模护栏bash scripts/test-scale.shT7-b,本地/按需;已并入 gates.sh),单测试文件 ≤800 行。

    测试铁律(摘要,完整七条见 S10 §5):黄金值必须有脚本出处 · 黑盒锁契约/白盒锁实现 · 禁止 actual == actual · 断言失败必须能定位到模块/行/格 · 负向优先于正向 · 评审看真值集合而非用例数 · 测试不得有破坏性副作用。


    #文档索引

    面向读者的口径与结论汇总在本文;实现细节、逐条口径、历史记录在下列文档 (随附代码实测与复跑方式)。文件名前缀 S1S9n 为按实现顺序编号的阶段文档。

    文档说明
    moonbit-项目目录设置-最佳实践.md目录/包/测试设置的官方依据 + 实证验证 + 落地清单
    moonbit-工具链与构建-setup-分析.md工具链安装、构建系统与 CI 集成;附录含仓库初始化与云原生构建配置记录
    mooncakes-发布方案.md发布入口:mooncakes.io 发布流程核验、元数据/命名/归档面评估、.moonignore 治理、版本策略与发布前门禁清单
    mooncakes-发布阻塞项3-4-落地方案.md发布落地:阻塞项 #3(归档面收敛 .moonignore,155→32 项)与 #4(发布前门禁 publish-check.sh)的深挖、实测与负向验证
    模块名迁移与发布链路核验.md迁移记录:mooncakes 账户定为 TryAndRun-TvT 后的全仓改名清单、Cannot find import ... 报错根因、moon publish --dry-run 退出码实测与 push 流水线移除后的本地门禁执行方式
    性能测试脚本-公开评审说明.md性能/体积测试脚本位置、参数口径与可复现路径(公开评审/审计入口)
    S9i-纯库调用体积探针与库实际体积.md库实际体积口径cmd/qr-min 纯库调用探针;体积金字塔 + 引用规范)
    S9j-层②统一Node对比-wasm-gc与fast_qr.md层② MoonBit 侧收敛为 wasm-gc;Node 进程内 shim 直测(性能主口径
    S9k-性能瓶颈与理论上限评估.md进程级差分把 auto build 拆为 5 段:瓶颈定位与理论上限(roadmap 依据
    S9n-优化方案复评与wasm-gc收敛审计.md收敛审计 + 单一优化优先级清单 + P0/P2/P2b 与 ReadOnlyArray 落地记录
    README示例二维码-SVG资源与生成.mdREADME 头部示例码为何用 SVG + 资产规格 + 生成脚本 + 一致性核验
    README优化-冗余清理与最佳实践.mdREADME 精简的冗余清单、官方 README 约定对照与取舍(含示例实测)
    S9o-性能与体积数据重测-与README冗余清理.md本轮重测记录:性能/体积数据刷新方法与归因 + README 去冗余清单
    S9p-宿主调用面性能口径-JS向wasm传参.md宿主调用面主口径:JS 反复带参调 wasm(cmd/host-probe + bench-host.sh);wasm-gc 传字符串的技术路径与踩坑(性能主口径
    S9q-性能口径统计差异与取平均评估.md统计口径:为什么 R 轮取最小≠真值;轮次级重抽样的 CV / 单跑失稳率 / 漂移判定;调度态与 Node 版本的量级对照;主数取中位数 + 必须报离散
    moonbit-实现布局与文件职责.md布局规则、lib/ + lib/internal/ 文件级职责、无环依赖、测试规划(维护者入口
    S10-测试用例设计与完善roadmap.md测试 roadmap v6:参考 fast_qr 测试体系盘点(含证据等级)+ 覆盖差距矩阵(G1–G15)+ 分阶段 T0–T7 路线 + 七条铁律;附录 D/E/F/G/H 为实跑结论(第三方解码回读、变异检测 21/21、v3/v4/v5 落地 + v6 订正记录)(测试维护入口
    S10c-select_capacity模式语义缺陷-定位与修复.mdv5 真 bug 修复记录:T3-d 探针首跑暴露的「显式模式未参与容量判定」缺陷——现象/根因/实测证据/修法/与参考 83,160 组参数对照/回归与变异项
    S10b-测试覆盖率报告.mdT5-a 覆盖率报告(行级,scripts/coverage.sh 产出)+ T5-b 不下降门禁(顶部 coverage-floor 机器可读标记)
    S11-无效代码与冗余文档清理评估.md清理评估入口:无效/冗余代码与文档的判定口径、实测清单、分级处置队列与执行纪律(Issue #63);§10 二次复核(修正 v1 的「能力缺口」误判)。逐轮落地记录见下条分册
    S11b-清理落地记录-v3-v5.md清理落地记录分册§11 v3 P0/P1 落地(删冗余符号、消 2 处双份实现、补 QRCode::empty、覆盖率 26→15)、§12 v4 文件级「无实践内容」(删纯注释文件 fast_qr_moonbit.mbt、合并薄委托文件 qr_output.mbt、删 3 个零信息符号)、§13 v5 注释级过期口径巡检(6 源码文件 9 处注释 + 11 文档订正,第 5 把尺子「口径引用有效性」)
    AGENTS.mdAI/协作者硬性约定:密钥安全、MoonBit 布局、文档死链零容忍(贡献前必读
    S1–S9n 实现系列文档按阶段编号的实现方案/记录/评审与性能评估全套(按需深入,从 S1 进入
    fast_qr 移植参考Rust 参考库 v0.14.0 的架构/接口/概念分析语料(由索引统辖
    项目基础框架-详细分析.md立项时的资产盘点、目标架构、移植策略与分阶段路线(历史基线
    wasm-编译与运行-结果分析.md历史记录:wasm 编译/运行全过程与早期多后端对比(wasm(WASI) 已移除)
    rust-环境配置脚本与fast_qr对比-setup.mdRust 参考环境配置(scripts/setup-rust.sh)+ fast_qr 对比用法

    行是该目录/系列的总入口(不再逐篇平铺,避免索引与文档本体重复)。 S11 是清理/收敛的评估入口(无效代码与冗余文档的判定口径 + 处置队列), 不替代 S10(测试覆盖面)与 S10b(覆盖率数字)。 其中 S1–S9n 每篇含「实现方案 / 实现记录 / 评审与优化」等分部,按阶段顺序编号; 性能相关重点篇目:S9b(优化路线与已否决项)、S9d(vs moonbit 生态)、S9f/S9g(历史体积口径)、 S9h(环境归因)、S9l(参考 fast_qr 拆解)、S9m(ReadOnlyArray)。


    #代码放置约定(方案 3:模块根无包,库包在 lib/

    本仓库模块根只放元数据(对齐 moonbitlang/core 形态):库包在 lib/、实现子包在 lib/internal/ (internal 永不反向 import lib,依赖无环)、CLI 在 cmd/不要建 src/(MoonBit 无此约定)。 测试放所属包目录内:*_test.mbt 黑盒(包外,仅 pub API)/ *_wbtest.mbt 白盒(包内,可访问私有实现), 两者不可混用;跨包依赖在使用方 moon.pkg 声明且声明后必须使用(否则 unused_package 告警致 moon check 失败)。

    完整约定表见 AGENTS.md,文件级职责详见 moonbit-实现布局与文件职责.md


    #项目结构

    . ├── moon.mod # MoonBit 模块配置(模块根不建包) ├── lib/ # 库包(公共 API,lib/moon.pkg) │ ├── ecl / version / mode / mask.mbt # 公共枚举(ECL/Version/Mode/Mask) │ ├── module.mbt # 公共 Module / ModuleType(单字节位打包) │ ├── qr.mbt # QRCode 结果容器 + QRCodeError + 访问器 │ ├── qr_build.mbt # 编排/构造:select_capacity + build_fixed/build │ ├── qr_builder.mbt # 公共 QRBuilder 构造器 │ ├── helpers.mbt # 输出层:终端画渲染 + QRCode::to_str/print │ ├── svg.mbt / shape.mbt # 输出层:SVG 渲染 + Shape 枚举 │ ├── *_test.mbt / *_wbtest.mbt # 黑盒测试 / 白盒测试 │ └── internal/ # 实现子包(各带 moon.pkg;不反向依赖 lib) │ ├── constants/ # 常量表 + 容量/元数据表 │ ├── bitstream/ # 位流缓冲(CompactQR) │ ├── reedsolomon/ # GF(256) 除法 + 交织 │ ├── data_encoding/ # 三模式编码 + 自动回退 │ └── matrix/ # module/matrix/placement/datamasking/score ├── cmd/main/ # CLI 可执行入口(演示终端画 + SVG) ├── cmd/bench/ # 性能基准(含 --dump 值全集导出) ├── cmd/qr-min/ # 纯库调用体积探针(库实际体积口径,零外壳) ├── docs/ # 项目文档(见上文「文档索引」) │ └── assets/ # 文档资源(qr-example.svg = README 示例码) ├── scripts/ # 构建与开发辅助脚本(见下节) ├── .githooks/ # 可选 Git 钩子(需自行启用) ├── .cnb.yml # 云原生构建(CNB CI)配置 ├── AGENTS.md # AI 协作代理指南 ├── README.md # 本文件(moon.mod 的 readme) └── LICENSE # Apache-2.0

    各文件职责的详细说明见 moonbit-实现布局与文件职责.md


    #开发与 CI

    • 代码门禁bash scripts/gates.sh(一键全量:moon fmt --check + moon check --deny-warn + moon test + 死链/规模护栏 + wasm-gc release 回归 + 差分门禁 + 发布前门禁; 支持 STAGES="check test" / SKIP_SLOW=1)。 push CI 已于 2026-09-14 移除(每次推送重复全量构建,资源收益不成比例), 门禁脚本零改动、改为本地/发布前按需执行,故提交前跑一遍是必须动作。 (不加 native 阶段——需系统 C 编译器。)
    • 发布bash scripts/publish.sh默认干跑:环境自检 + 发布前门禁 + 归档清单 + moon publish --dry-run);真实发布 bash scripts/publish.sh --publish(不可逆,需确认)。 凭据属本地私有,发布不进 CI
    • 基准复跑:见性能与体积的复跑入口;参数口径见 性能测试脚本-公开评审说明.md
    • Git 钩子(可选)git config core.hooksPath .githooks(个人本地配置,仓库不代设)。
    • 编码 / 提交规范:见 AGENTS.md(密钥安全、MoonBit 布局、文档死链零容忍等硬性约定)。

    scripts/ 按角色分组(push CI 已移除;门禁链由 gates.sh 本地一键触发,环境配置与对外对比脚本仅本地/审计时手动执行):

    角色脚本执行方式
    环境配置setup-moonbit.shsetup-rust.shsetup-fast-qr-wasm-env.sh手动(幂等,本地/审计)
    全量门禁gates.shfmt-checkchecktestdocs-link-checktest-scalebuild-and-rundiff-gatepublish-check本地
    发布publish.sh(默认干跑;--publish 才真发,需确认)本地(不进 CI)
    门禁链单项fmt-check.shcheck.shtest.shbuild-and-run.sh本地(亦由 gates.sh 串起)
    性能基准bench-host.sh + host-bench.mjs(宿主调用面:JS 反复带参调 wasm,主口径)bench-host-var.sh + bench-host-var.mjs(统计稳定性:CV / 单跑失稳率 / 漂移)、bench.sh(层①)、bench-layer2.sh + gc-compare.mjs(层② vs fast_qr)
    体积基准bench-size.sh + wasm-size.mjs(同规则口径 + 纯库探针 + 语义护栏)
    外部检出build-fast-qr-wasm.sh(fast_qr 侧产物,检出副本不入库)
    测试审计test-audit.sh(变异检测 + 解码回读)+ apply-mutation.py + qr-decode-check.mjs--points 三基准点 / --corpus T3-d 54 组
    黄金值/规模gen-goldens.sh(钉版重建 + --verify 四项)+ snapshot_gen_tables.py / snapshot_gen_default.py / snapshot_gen_rs_vectors.rs / snapshot_gen_score.rs / snapshot_gen_placement.rs + snapshot_verify_*.py + test-scale.sh(单测试文件 ≤800 行护栏)
    差分门禁diff-gate.sh(vs 参考 wasm 逐位 sha256;无制品显式 skipped)本地(可 skipped)
    覆盖率coverage.shmoon coverage analyze 报告)+ --floor 不下降门禁(T5-b)
    文档/规模护栏docs-link-check.sh(T6-c 相对链接死链) + test-scale.sh(T7-b 单测试文件 ≤800 行)本地
    资源生成gen-readme-qr-svg.sh(重建 docs/assets/qr-example.svg,临时包用完即删)


    #问题反馈与贡献

    • 问题与建议:提交至仓库 Issue
    • 贡献流程:改动前请阅读 AGENTS.md(密钥安全、MoonBit 布局、文档死链零容忍等 硬性约定),并跑通开发与 CI 中的收尾检查后再提交。


    #License