压缩接口规范 0.1.0
本包在宿主的原生解压流上提供两种能力:限量的 raw deflate 解压,以及带 CRC-32 与大小校验的 ZIP 条目解压。它是云工专用能力,不使用绑定,也不需要资源许可。输入是字节串,结果是 (整数 合 字节串):整数为状态码,字节串为解压结果(状态非 0 时为空字节串)。可恢复的数据问题用状态码返回;参数违规、输入过大、最大输出越界抛出豫言异常,应用可用「尝试运行」捕获。
状态码
| 状态 | 含义 | 适用函数 |
| --- | --- | --- |
| 0 | 成功;结果就是完整的解压输出 | 两个函数 |
| 1 | 输出超过上限;读取时累计超限即取消,不继续解压 | 两个函数 |
| 2 | 数据损坏或不完整(含尾随多余字节) | 两个函数 |
| 3 | 数据可以解压,但 CRC-32 或解压大小与预期不符 | 仅 解压归档条目 |
状态 1 的判定不看预期:只要解压输出的累计字节数大于最大输出就立即取消解压流并返回 1;输出恰好等于最大输出算成功。
解压原始压缩
解压原始压缩 接收 raw deflate 字节串(无 zlib、无 gzip 头,即 ZIP 内部的压缩方法 8)和最大输出字节数,返回 (状态 合 结果)。
- 输入不得超过 16 MiB(宿主值桥的交换上限),最大输出须在 1 至 134217728(128 MiB)之间;越界抛出豫言异常。128 MiB 是接口允许的上限而不是推荐值:结果保存在 Wasm 内存里,应用应按自己的内存预算选择最大输出(Cloudflare Workers 的内存上限约为 128 MB)。
- 对合法的输入,结果与 Node 的
zlib.inflateRawSync逐字节相同,包括空输出的合法流(如03 00,得状态 0 与空字节串)、存储块、静态与动态哈夫曼块及跨多个输出块的大结果。 - 空输入、被截断的流、损坏的流为状态 2。流结束后还有多余字节(含两个流首尾相接)也是状态 2:这与浏览器、workerd 和 Node 的
DecompressionStream一致,不同于zlib.inflateRawSync(它忽略尾随字节)。 - 压缩炸弹(很小的输入、极大的输出)不会被整体解出:读取每个输出块时先核对累计长度,越限即取消。
- 既损坏又超限的数据,宿主流缓冲深度不同,可能先给出块(状态 1)也可能先报错(状态 2);应用应把非 0 的状态一律当作失败。
解压归档条目
解压归档条目 参数依次为:条目数据、方法、预期 CRC-32、预期解压大小、最大输出字节数。它服务于 ZIP 归档解析库:库按中央目录读到方法、CRC-32、大小,把本地文件头之后、长度恰为压缩大小的条目数据交给本函数。
- 方法:
0存储(数据即原文),8raw deflate;其他方法抛出豫言异常。 - 预期 CRC-32 须在 0 至 4294967295 之间;预期解压大小须在 0 至最大输出之间(预期大于最大输出是调用方的参数错误,抛出异常);最大输出须在 1 至 134217728 之间;数据不超过 16 MiB。违规均抛出豫言异常。
- 状态 0:数据完整、CRC-32 与解压大小都与预期相等,结果是校验过的解压输出。校验由宿主原生完成,不在豫言里逐字节计算。
- 状态 1:输出超过最大输出。因为预期大小来自不可信的归档目录,可以比实际小:“说谎”的条目照样受最大输出限制。
- 状态 2:deflate 流本身损坏、被截断或有尾随多余字节。存储方法的数据是任意字节,永远不会是状态 2。
- 状态 3:数据可以解压(流本身合法)而 CRC-32 或大小与预期不符;存储方法的数据长度不等于预期大小也是 3。
- 优先级:存储方法先比较长度——数据长度大于最大输出为 1,否则不等于预期大小为 3,否则进入校验;deflate 方法由宿主解压流校验,失败后再用 raw deflate 复解一遍来区分:复解超限为 1,复解失败为 2,复解成功则是 CRC-32 或大小不符,为 3。这样无论宿主流是先交出块还是先报错,状态都相同(既损坏又超限的数据除外,同上)。
限额
| 项目 | 上限 | 违规时 | | --- | --- | --- | | 输入字节数 | 16 MiB | 豫言异常 | | 最大输出字节数 | 1 至 134217728 | 豫言异常 | | 预期解压大小 | 0 至最大输出 | 豫言异常 | | 预期 CRC-32 | 0 至 4294967295 | 豫言异常 |
跨宿主一致性
任何宿主的实现须满足:状态码语义与上面相同;合法输入的结果字节与 zlib 的 raw inflate 相同;累计超限即停止解压;尾随多余字节为状态 2;CRC-32 与大小校验由原生解压库完成。云工适配用 DecompressionStream('deflate-raw') 解压,用 DecompressionStream('gzip') 借 gzip 尾部的 CRC-32 与 ISIZE 校验条目(把条目包成 gzip 容器,存储方法的数据先包成 deflate 存储块);其他宿主可以用原生 zlib 达到同样的可观察结果。
一致性样例
解压原始压缩对zlib.deflateRawSync("abc")与最大输出 10:(0 合 "abc");最大输出 2:(1 合 空);最大输出 3:(0 合 "abc")。解压原始压缩对空输入:(2 合 空);对03 00:(0 合 空);对合法流后接 1 个字节:(2 合 空)。解压归档条目对"123456789":方法 0,CRC-320xCBF43926,大小 9:(0 合 "123456789");CRC-32 改为 0:(3 合 空);大小改为 8 或 10:(3 合 空);最大输出 8(预期大小仍为 9):抛出异常。- 存储条目长度 0、1、65534、65535、65536、65537、131070、131071 字节的校验都为 0(覆盖存储块边界);deflate 条目被改动一个字节:能解压则为 3,不能则为 2。
边界
本包只解压单个条目的数据,不解析 ZIP 目录、本地文件头、加密、Zip64 或数据描述符,也不提供压缩。CRC-32 不作为独立函数提供:纯豫言逐字节计算太慢,而平台的 Web Crypto 没有 CRC-32,所以校验只经由解压完成。结果字节串存放在 Wasm 内存里,超过宿主内存预算的输出属于应用选择最大输出时的责任。