ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unison 语言 Nat 字节编码指南:用 encodeNat*be/le 与 decodeNat* 实现大端小端往返测试

Unison 语言 Nat 字节编码指南:用 encodeNat*be/le 与 decodeNat* 实现大端小端往返测试 编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载导读本文围绕 Unison 语言仓库中的unison-src/transcripts-using-base/binary-encoding-nats.md转录测试文档系统讲解Bytes库中 16/32/64 位大端Big Endian与小端Little Endian编码原语的使用方法。你将掌握encodeNat64be、decodeNat64le等内置函数的签名与行为、如何编写结构化的编码/解码往返测试以及这些原语在运行时中的真实实现位置可直接运用于自有的 Unison 数据序列化场景。一、文档定位一份“编码原语往返验证”转录binary-encoding-nats.md位于仓库的unison-src/transcripts-using-base/目录。这个目录下的转录transcript都依赖base.u提供的基础库且按目录内 README 的说明只使用新运行时new runtime运行。该文档的真实性质是一次可执行测试演示它用 Unison 源码定义一个抽象的“编码方案”类型并针对一组精心挑选的Nat值逐一验证六种内置编码/解码函数组合是否满足“解码是编码的逆运算、且不残留多余字节”。与其配套的 binary-encoding-nats.output.md 记录了实际执行结果——最终68 个测试全部通过✅ 68 test(s) passing即文档中的全部测试用例均真实可运行、结论可复现。二、六种内置原语签名与行为文档的核心是六个由Bytes库提供的内置函数它们在 parser-typechecker/src/Unison/Builtin.hs 中被声明为内置builtin能力B Bytes.encodeNat64be $ nat -- bytes, B Bytes.encodeNat64le $ nat -- bytes, B Bytes.encodeNat32be $ nat -- bytes, B Bytes.encodeNat32le $ nat -- bytes, B Bytes.encodeNat16be $ nat -- bytes, B Bytes.encodeNat16le $ nat -- bytes, B Bytes.decodeNat64be $ bytes -- optionalt (tuple [nat, bytes]), B Bytes.decodeNat64le $ bytes -- optionalt (tuple [nat, bytes]), B Bytes.decodeNat32be $ bytes -- optionalt (tuple [nat, bytes]), B Bytes.decodeNat32le $ bytes -- optionalt (tuple [nat, bytes]), B Bytes.decodeNat16be $ bytes -- optionalt (tuple [nat, bytes]), B Bytes.decodeNat16le $ bytes -- optionalt (tuple [nat, bytes]),可归纳为下表函数签名类型语义Bytes.encodeNat64beNat - Bytes将Nat编码为 64 位大端字节序列Bytes.encodeNat64leNat - Bytes将Nat编码为 64 位小端字节序列Bytes.encodeNat32beNat - Bytes将Nat编码为 32 位大端字节序列Bytes.encodeNat32leNat - Bytes将Nat编码为 32 位小端字节序列Bytes.encodeNat16beNat - Bytes将Nat编码为 16 位大端字节序列Bytes.encodeNat16leNat - Bytes将Nat编码为 16 位小端字节序列Bytes.decodeNat64beBytes - Optional (Nat, Bytes)从字节序列头部解码一个 64 位大端Nat返回数值与剩余字节Bytes.decodeNat64leBytes - Optional (Nat, Bytes)从字节序列头部解码一个 64 位小端Nat返回数值与剩余字节Bytes.decodeNat32beBytes - Optional (Nat, Bytes)解码一个 32 位大端NatBytes.decodeNat32leBytes - Optional (Nat, Bytes)解码一个 32 位小端NatBytes.decodeNat16beBytes - Optional (Nat, Bytes)解码一个 16 位大端NatBytes.decodeNat16leBytes - Optional (Nat, Bytes)解码一个 16 位小端Nat三个关键行为特征编码端固定宽度64 位编码总是产出 8 字节32 位编码产出 4 字节16 位编码产出 2 字节若Nat数值超出该宽度所能表示的范围从源码结构看应理解为截断到低位字节对应宽度后再编码。解码端返回剩余输入解码函数返回Optional (Nat, Bytes)其中第二个元素是解码后“剩下的字节”。这一设计使解码函数天然适合流式解析——调用方可以持续对remain继续解码从而拼接出任意长度的字节流协议。失败返回None当输入字节不足以构成完整解码例如给 64 位解码器传入 2 个字节时返回None。三、文档中的测试设计抽象“编码方案”驱动通用往返逻辑文档先用unique type定义一个携带解码器与编码器的抽象类型EncDecunique type EncDec EncDec Text (Nat - Bytes) (Bytes - Optional (Nat, Bytes)) BE64 EncDec 64 bit Big Endian encodeNat64be decodeNat64be LE64 EncDec 64 bit Little Endian encodeNat64le decodeNat64le BE32 EncDec 32 bit Big Endian encodeNat32be decodeNat32be LE32 EncDec 32 bit Little Endian encodeNat32le decodeNat32le BE16 EncDec 16 bit Big Endian encodeNat16be decodeNat16be LE16 EncDec 16 bit Little Endian encodeNat16le decodeNat16leEncDec的三个字段分别是人类可读的标签Text、编码函数Nat - Bytes和解码函数Bytes - Optional (Nat, Bytes)。六个具体值BE64、LE64、BE32、LE32、BE16、LE16把标签与真实的内置原语绑定之后所有测试代码都可以只依赖抽象层不再关心具体字节序——这正是该文档设计的精髓同样的testRoundTrip逻辑被复用到六种方案上。核心验证函数testRoundTrip对给定数值n和编码方案EncDec执行完整往返检查testRoundTrip : Nat - EncDec - {IO, Stream Result} () testRoundTrip n cases EncDec label enc dec - encoded enc n match dec encoded with Some (n, remain) - if n n then emit (Ok (successfully decoded (toText n) using label)) else emit (Fail (decoded (toText n) instead of (toText n) using label)) if (size remain) 0 then emit (Fail (unconsumed input using label)) else emit (Ok (consumed all input)) None - emit (Fail (failed to decode (toText n) using label))它依次断言三件事把“正确往返”拆成可独立诊断的细粒度结果解码不失败dec encoded必须返回Some若返回None则直接报Fail数值保真解码出的n必须与原值n相等输入完全消费解码剩余字节remain的长度必须为 0否则报unconsumed input。每次检查都通过emit向Stream Result流中输出一个Ok/Fail结果错误信息中带上具体数值与方案标签方便在测试报告中快速定位失败来源。四、测试用例构造按数值量级裁剪编码方案testNat依据数值大小决定启用哪些编码方案避免给不兼容的宽度浪费测试时间testNat : Nat - {IO, Stream Result} () testNat n _ if n (shiftLeft 1 32) then testRoundTrip n BE64 testRoundTrip n LE64 else if n (shiftLeft 1 16) then testRoundTrip n BE64 testRoundTrip n LE64 testRoundTrip n BE32 testRoundTrip n LE32 else testRoundTrip n BE64 testRoundTrip n LE64 testRoundTrip n BE32 testRoundTrip n LE32 testRoundTrip n BE16 testRoundTrip n LE16选择规则清晰任何数值都必须经 64 位大端/小端验证64 位是Nat的“全量”宽度n 2^16时额外验证 32 位方案n 2^16时再叠加 16 位方案。这样测试矩阵既覆盖了每种编码器的完整能力又不会对不匹配的宽度做无意义测试。testABunchOfNats用runTest串联七个精心选择的数值testABunchOfNats _ (runTest (testNat 0xFFFFFFFF)) (runTest (testNat 0x41000000)) (runTest (testNat 0x00410000)) (runTest (testNat 0x00004100)) (runTest (testNat 0x86753099)) (runTest (testNat 0x00000041)) (runTest (testNat 0))这些值并非随机而是刻意覆盖多种边界与形态0xFFFFFFFF32 位全 1是 32 位编码器的最大输入0x41000000、0x00410000、0x00004100非零字节依次出现在最高、中间、低位位置用于验证字节序处理是否正确同样的数值在不同字节序下字节排列完全不同0x86753099一个普通的中等大小随机数0x0000004165的十六进制写法只占用最低一个字节ASCIIA的码值0最小的Nat全零字节序列的极端情况。把65即0x41和0纳入测试确保“低位只有个别字节非零”与“全部为零”这两种退化输入也不会出错。五、运行与验证add 之后 io.test文档末尾给出两条 UCM 命令 add io.test testABunchOfNats add把当前 scratch 文件中的EncDec类型、六个EncDec值与三个测试函数加入 codebase。从配套输出可见 UCM 报告新增了type EncDec、BE16/BE32/BE64/LE16/LE32/LE64、testABunchOfNats、testNat、testRoundTrip等条目 io.test testABunchOfNats在 IO 中执行测试并流式打印每个Ok/Fail结果。运行环境需要依赖base.u提供的runTest、Result等基础设施这正是本目录转录统一预加载 base.u 的原因。测试报告逐行输出如◉ successfully decoded 4294967295 using 64 bit Big Endian、◉ consumed all input的成对结果最终统计为68 个测试全部通过7 组数值 × 各组适用的方案数 × 每组 2 项断言合计其中 64 位方案 7 个数值×2 断言×2 字节序28 项32 位方案 6 个数值×2 断言×2 字节序24 项16 位方案 4 个数值×2 断言×2 字节序16 项共 68 项与输出完全吻合。六、源码纵深这些原语在运行时如何落地这六个编码/解码原语不是 Unison 语言层的语法糖而是以**内置函数builtin/foreign function**形式接入运行时的。类型声明层parser-typechecker/src/Unison/Builtin.hs 为每个原语声明了类型与名称如Bytes.encodeNat64be、Bytes.decodeNat64be供类型检查器与代码库引用。运行时绑定层unison-runtime/src/Unison/Runtime/Builtin.hs 中declareForeign Untracked 1 Bytes_encodeNat64be等声明把这些名字绑定为 foreign 函数unison-runtime/src/Unison/Runtime/Foreign/Function/Type.hs 定义对应的构造器unison-runtime/src/Unison/Runtime/Foreign/Function.hs 中的mkForeign将实际实现挂接到宿主语言HaskellBytes_decodeNat64be - mkForeign $ pure . Bytes.decodeNat64be Bytes_decodeNat64le - mkForeign $ pure . Bytes.decodeNat64le Bytes_decodeNat32be - mkForeign $ pure . Bytes.decodeNat32be Bytes_decodeNat32le - mkForeign $ pure . Bytes.decodeNat32le Bytes_decodeNat16be - mkForeign $ pure . Bytes.decodeNat16be Bytes_decodeNat16le - mkForeign $ pure . Bytes.decodeNat16le Bytes_encodeNat64be - mkForeign $ pure . Bytes.encodeNat64be Bytes_encodeNat64le - mkForeign $ pure . Bytes.encodeNat64le Bytes_encodeNat32be - mkForeign $ pure . Bytes.encodeNat32be Bytes_encodeNat32le - mkForeign $ pure . Bytes.encodeNat32le Bytes_encodeNat16be - mkForeign $ pure . Bytes.encodeNat16be Bytes_encodeNat16le - mkForeign $ pure . Bytes.encodeNat16le也就是说编码/解码的字节序逻辑最终由 Haskell 的Bytes模块实现Unison 层通过 foreign call 直接调用。这在仓库的其他转录中也有印证例如 benchmarks/tmap.u 用encodeNat64be生成 TMap 的键reparses-with-same-hash.u 用encodeNat64be拼接哈希字节。七、实践要点把该模式复用到你自己的序列化代码从这份转录可以提炼出一套可直接复用的编码/解码测试模式用抽象类型封装编码方案定义一个携带标签、编码器、解码器的 record/unique type把“字节序选择”参数化测试逻辑与具体方案解耦断言三件事解码成功非None、数值保真n n、无剩余字节size remain 0三者缺一不可任何一项失败都代表编码实现或调用有误覆盖边界值全 1 最大值、非零字节出现在不同位阶的数值、仅最低字节非零、全零——这些用例能一次性暴露字节序、截断与补零方面的典型 bug按量级裁剪方案对小数值跳过超出其表示范围的宽编码器既节省测试时间又避免无效断言用emit/Stream Result输出可读结果为每个断言单独产生Ok/Fail配合io.test得到逐项可读的测试报告参考 _base.md 中的测试基础设施以及hex (fromHex str) str之类的基准用例。如果你正在为 Unison 项目编写网络协议、文件格式或哈希相关的序列化逻辑encodeNat64be/le、decodeNat64be/le这套原语配合上述往返测试模式即可获得字节序正确、边界安全、可回归验证的二进制编解码层。赞分享编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载相关推荐用真实 JSON-RPC 往返验证 Serverless Framework 的 MCP 部署端到端测试完整指南用真实 JSON RPC 往返验证 Serverless Framework 的 MCP 部署端到端测试完整指南 导读 在 Serverless Framew开发工具CLI云原生后端gnet字节序处理大端小端转换的高效实现gnet字节序处理大端小端转换的高效实现 你是否曾在网络编程中遭遇过诡异的数据解析错误明明发送的是16位整数0x1234接收端却解析为0x3412这种令后端网络通信用自然语言编写 E2E 测试Shortest AI 端到端测试框架完全指南用自然语言编写 E2E 测试Shortest AI 端到端测试框架完全指南 Shortest 是一个由 AI 驱动的端到端测试框架开发者可以用纯自然语言如测试质量保障AI 应用开发工具上一篇riscv-rust入门教程3步快速搭建RISC-V本地开发环境下一篇Vlc.DotNet实战案例构建支持流媒体播放的.NET应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表