#io-error #read-write #io #io-read #embedded-io #read #write

no-std genio

一个类型安全的、低级的 std::io 替代品。支持嵌入式开发中的 no_std,只需禁用 cargo 功能 std。由于 std::io::Error 类型存在限制,genio 提供了 ReadWrite 特性,允许实现者选择自己的类型。这种类型可以更好地表达可能发生的错误类型。

3 个不稳定版本

使用旧的 Rust 2015

0.2.1 2019 年 12 月 23 日
0.2.0 2019 年 2 月 22 日
0.1.0 2017 年 1 月 28 日

嵌入式开发 中排名第 267

Download history 63/week @ 2024-03-13 278/week @ 2024-03-20 511/week @ 2024-03-27 964/week @ 2024-04-03 488/week @ 2024-04-10 487/week @ 2024-04-17 111/week @ 2024-04-24 342/week @ 2024-05-01 702/week @ 2024-05-08 501/week @ 2024-05-15 240/week @ 2024-05-22 298/week @ 2024-05-29 328/week @ 2024-06-05 1087/week @ 2024-06-12 786/week @ 2024-06-19 52/week @ 2024-06-26

每月下载量 2,324
3 个 包中使用

MIT/Apache 协议

64KB
1K SLoC

通用 IO

一个类型安全的、低级的 std::io 替代品。

支持嵌入式开发中的 no_std,只需禁用 cargo 功能 std

动机

标准库中可以找到的 IO 例程非常有用。然而,由于它们使用 io::Error 作为唯一的错误类型,它们存在以下问题

  • 无法在类型中表达无故障操作(例如,内存操作)。
  • 如果您知道操作不会失败,您仍然需要调用 unwrap()。如果您犯了错误,您将获得运行时错误。
  • 编译器必须插入检查(比较和分支),这会减慢代码速度。当然,可以通过内联和优化来消除它,但这并不是确定的事情。
  • io::Error 可能会分配,这不仅会使速度变慢,还会阻止在裸金属上使用。
  • io::Error 非常宽泛,在某些情况下可能包含无意义值(例如,在执行 read() 时磁盘已满)。完美的程序不应该忽略这些值,但很难决定如何处理它们。
  • 您只能使用 ErrorKind 合理地决定如何处理错误。这样可能会丢失一些信息。
  • io::Error 传播到其他接口并污染它们。例如,protobuf 解析器“可能”在读取内存的情况下返回它。Tokio-core 在每个地方都使用 io::Error
  • 有时很难从签名中了解确切可能失败的原因以及如何处理错误。例如,你知道为什么 tokio_core::reactor::Core::new() 可能失败以及如何处理错误吗?

genio 的目的是通过更好地利用 Rust 的类型系统来解决这些问题。它借鉴了 std::io 的许多想法,但有一个重要区别:ReadWrite 特性可以定义自己的错误。还有许多用于处理错误以及 std::io 的粘合剂工具。

由于所有实现了 genio::{Read, Write} 的内容都可以简单地实现 std::io::{Read, Write},因此最好只为 genio 编写算法,并让用户将它们包装在粘合剂中。

贡献

这个包当然不是完成的项目,它需要更多的工作才能与 std::io 完美地工作。实现更多的算法、包装器和工具也将是有益的。最后,其他包应该开始使用 genio。我邀请大家帮助改进这个包,使其尽可能好。

我对您能想象到的每个 PR 都持开放态度。

状态

虽然 ReadWrite 特性中的必需类型和方法不太可能改变,但这个包被认为是未稳定的。目前,只有 同步流 的特型。如果你的类型不是同步流,请不要实现这些特型,但请帮助设计其他特型。

计划

  • 同步流
  • 异步流
  • 已知消息大小的同步消息流(通常在消息的头部)
  • 未知大小的同步消息流(通常使用一些分隔符)
  • 已知消息大小的异步消息流(通常在消息的头部)
  • 未知大小的异步消息流(通常使用一些分隔符)
  • 对原始类型的良好实现
  • std::io 类型的良好实现
  • partial-io 集成

当然,还有所有这些的组合子。

《genio》和《std::io》之间的差异

除了关联的错误类型之外,还有其他差异。最重要的是,《genio》旨在实现更薄的包装和层。例如,它不会自动处理EINTR,而是需要你自己处理 - 例如,使用《Restarting》包装器。这让你更好地控制代码中的情况,同时也简化了包装器的实现。

某些操作使用略微不同的类型。《read_exact》除了返回更底层的错误类型外,还可能返回《UnexpectedEnd》。链式组合了两种错误类型。《read_to_end》允许使用任何可以从reader扩展的类型。刷新可能返回与《write()`》不同的错误。如果没有要刷新的内容,它可能返回《Void》类型。

此外,《read()`》可能提示没有足够的字节(在错误情况下可用于跳过读取),而《Write》可能提示将要写入的字节数。(这还不稳定。)

空白实现

故意没有为《std::io》或反之提供《genio》特质的空白实现。这是为了让人们能够实现这两个特质。如果你在你的crate中使用《std::io》特质,你可以添加对《genio》的支持而无需担心。请不要使用关联类型为《io::Error》的《genio》特质进行实现。如果你没有时间编写完整的实现,坚持使用粘合包装器。不要浪费实现《genio》最佳方式的机会!

免责声明

我非常感激Rust开发者们为创建《std::io》所付出的辛勤努力。《genio》crate并不是为了贬低他们、评判他们等。他们可能没有足够的时间来实现这样的事情,或者担心它可能过于复杂。这个crate的目标是通过为想要更多通用IO的人们提供工具来改善世界。

依赖关系