#cobs #fuzz-testing #no-std

no-std corncobs

为Rust no_std目标提供COBS编码/解码

3个版本

0.1.3 2022年11月10日
0.1.1 2022年2月6日
0.1.0 2022年2月6日

#266 in 嵌入式开发

Download history 2342/week @ 2024-03-14 2547/week @ 2024-03-21 3242/week @ 2024-03-28 3811/week @ 2024-04-04 2251/week @ 2024-04-11 2113/week @ 2024-04-18 2580/week @ 2024-04-25 1977/week @ 2024-05-02 3057/week @ 2024-05-09 2023/week @ 2024-05-16 1776/week @ 2024-05-23 2215/week @ 2024-05-30 1590/week @ 2024-06-06 1565/week @ 2024-06-13 2797/week @ 2024-06-20 1651/week @ 2024-06-27

8,061 每月下载量
4 个包中使用了 (3 直接)

MPL-2.0 许可证

33KB
284

corncobs: Rust中的玉米芯COBS编码/解码

此包为Rust程序提供一致开销字节填充 (COBS) 支持,特别关注资源受限的嵌入式 no_std 目标

  • 提供快速(缓冲区到缓冲区)和小型(就地或迭代器基础)版本的编码和解码例程。

  • 提供一个用于计算给定输入大小的最大编码大小的 const fn,这样您可以在不使用魔法数字的情况下精确地定义固定大小的缓冲区。

  • 测试覆盖率良好,包括Criterion基准和honggfuzz模糊测试套件,以尝试确保代码质量。

Cargo features

默认情况下没有启用功能。嵌入式程序员在使用 corncobs 时无需指定 default-features = false,因为谁说 std 应该是默认的?那些拥有大量RAM的人。

功能

  • std: 如果您在一台具有“无限内存”的“大型计算机”上,并且可以承担动态内存分配固有的非确定性,则此功能将启用编码到/从 Vec 的例程,以及为 CobsError 实现的 Error

何时使用COBS

COBS允许我们将任意字节块转换为略微更长的字节块,该字节块不包含特定字节,除非作为最后的终止符。 corncobs 实现了这种版本,其中字节是零。也就是说,corncobs 可以将任意字节序列转换为略微更长的序列,该序列除了最后之外不包含零。

您想这样做的主要原因在于封装。如果您在流中传输一系列消息,您需要一种方法来标识消息的开始和结束位置。有许多种方法可以实现这一点——例如,在每条消息前传输长度——但其中大多数不支持同步恢复。同步恢复使得接收器能够在流的任何位置调整接收,并正确地找出下一个消息边界。提供同步恢复的最简单方法是在每条消息的开始/结束处使用一个标记,可以可靠地将它与消息中的数据进行区分。要在一个任意的数据流中找到消息边界,您只需查找当前消息的末尾,并从那里开始解析。COBS可以通过确保消息终止符字符(0)仅出现在消息之间来完成这一点。

与许多封装方法(特别是SLIP)不同,COBS保证了编码输出大小的上限:原始长度,加上两个字节,加上每254个输入字节一个字节。《code>corncobs提供了一个max_encoded_len函数,用于在编译时为缓冲区尺寸进行大小调整,以便允许最坏情况的编码开销。

何时使用此COBS实现

我为一个需要通过80MHz Cortex-M4上的3-10 Mbit/s RS485链路进行视频流传输的艺术项目编写了corncobs。它的性能对于这项任务来说是足够的。

当时,我已经确定了两种主要的替代方案:cobs-rspostcard-cobs。(注意:postcard-cobs称其为cobs-rs的分支,但实际上它是对cobs的分支。这也让我感到困惑。)它们并不完全适用于我的应用程序

  • 大约每8个CPU周期处理一个输入比特,我需要解码非常快。corncobs的解码速度快约60倍,满足了我的需求。(编码速度约快3倍。这两个数字都是针对非病态数据的,即不是所有零。有关详细信息,请参阅基准测试套件。)

  • 我通过DMA在环形缓冲区中接收消息,它们会被连接起来,但用零分开。这意味着我无法在编译时表达传入消息的长度,并且我需要为每条消息消耗确切的字节数,这使得使用cobs-rs变得困难。

  • 我在一个数据传输不太可靠的环境中操作,需要固件能够从损坏或丢失的数据中优雅地恢复,即不会崩溃。这使得使用postcard-cobs变得困难。(他们没有公共的错误跟踪器,所以我无法报告崩溃。)

然而,corncobspostcard-cobs是兼容的;corncobs中的tests/compat.rs测试套件证明了这一点。(注意,您需要确保在将数据传递给postcard-cobs之前删除尾随零,以避免崩溃。)corncobs也与cobs-rs大部分兼容,除了空消息的编码,我认为这是cobs-rs中的一个错误。因此,您可以混合使用——如果您想获得postcard-cobs的更慢但更可预测的编码性能和corncobs的更快的解码速度,那么您可以选择这样做。

我用来得出这些结论的性能测试已经通过了。我会留意它们,以防有一天我可以停止维护自己的crate。:-) 你可以使用以下命令运行它们:

$ cargo bench comparison

使用COBS的技巧

如果你正在设计一个协议或消息格式并考虑使用COBS,你有一些选择。

优化大小:当被编码的数据包含0x00字节时,COBS编码的冗余最小,至少每发送254字节就有一个。在实践中,大多数数据格式都能达到这个效果。然而...

优化速度:COBS编码/解码,尤其是corncobs实现,当数据中尽可能少地包含0x00字节时(理想情况下没有)运行得最快。如果你能调整你要编码的数据以避免零,你可以实现更高的编码/解码速率。例如,在我发送RGB视频数据的一个项目中,我只是将红色/绿色/蓝色值1声明为与0相同,并将所有0转换为1,从而实现了很大的性能提升。

运行测试和其他内容

为了未来的自己,当我忘记咒语时。或者为了你!

测试:cargo test

基准测试:cargo bench(到目前为止很容易)

模糊测试

cargo install honggfuzz
cargo hfuzz run encode  # or...
cargo hfuzz run decode

无运行时依赖