Skip to content

Commit d6f6419

Browse files
committed
Add embedded-io-async.
1 parent 1b5a858 commit d6f6419

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ members = [
88
"embedded-hal-bus",
99
"embedded-can",
1010
"embedded-io",
11+
"embedded-io-async", # nightly-only
1112
]

embedded-io-async/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "embedded-io-async"
3+
version = "0.5.0"
4+
edition = "2021"
5+
description = "Async embedded IO traits"
6+
repository = "https://github.com/rust-embedded/embedded-hal"
7+
readme = "README.md"
8+
license = "MIT OR Apache-2.0"
9+
categories = [
10+
"embedded",
11+
"no-std",
12+
]
13+
14+
[dependencies]
15+
embedded-io = { version = "0.5", path = "../embedded-io" }

embedded-io-async/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[![crates.io](https://img.shields.io/crates/d/embedded-io-async.svg)](https://crates.io/crates/embedded-io-async)
2+
[![crates.io](https://img.shields.io/crates/v/embedded-io-async.svg)](https://crates.io/crates/embedded-io-async)
3+
[![Documentation](https://docs.rs/embedded-io-async/badge.svg)](https://docs.rs/embedded-io-async)
4+
5+
# `embedded-io-async`
6+
7+
Async IO traits for embedded systems.
8+
9+
This crate contains asynchronous versions of the [`embedded-io`](https://crates.io/crates/embedded-io) traits and shares its scope and design goals.
10+
11+
This project is developed and maintained by the [HAL team](https://github.com/rust-embedded/wg#the-hal-team).
12+
13+
## Minimum Supported Rust Version (MSRV)
14+
15+
This crate requires Rust nightly newer than `nightly-2022-11-22`, due to requiring support for
16+
`async fn` in traits (AFIT), which is not stable yet.
17+
18+
Keep in mind Rust nightlies can make backwards-incompatible changes to unstable features
19+
at any time.
20+
21+
## License
22+
23+
Licensed under either of
24+
25+
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
26+
<http://www.apache.org/licenses/LICENSE-2.0>)
27+
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
28+
29+
at your option.
30+
31+
### Contribution
32+
33+
Unless you explicitly state otherwise, any contribution intentionally submitted
34+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
35+
dual licensed as above, without any additional terms or conditions.

embedded-io-async/src/lib.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#![no_std]
2+
#![feature(async_fn_in_trait, impl_trait_projections)]
3+
#![cfg_attr(docsrs, feature(doc_cfg))]
4+
#![warn(missing_docs)]
5+
#![doc = include_str!("../README.md")]
6+
7+
pub use embedded_io::{Error, ErrorKind, Io, ReadExactError, SeekFrom, WriteAllError};
8+
9+
/// Async reader.
10+
///
11+
/// Semantics are the same as [`std::io::Read`], check its documentation for details.
12+
pub trait Read: Io {
13+
/// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
14+
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
15+
16+
/// Read the exact number of bytes required to fill `buf`.
17+
async fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
18+
while !buf.is_empty() {
19+
match self.read(buf).await {
20+
Ok(0) => break,
21+
Ok(n) => buf = &mut buf[n..],
22+
Err(e) => return Err(ReadExactError::Other(e)),
23+
}
24+
}
25+
if !buf.is_empty() {
26+
Err(ReadExactError::UnexpectedEof)
27+
} else {
28+
Ok(())
29+
}
30+
}
31+
}
32+
33+
/// Async buffered reader.
34+
///
35+
/// Semantics are the same as [`std::io::BufRead`], check its documentation for details.
36+
pub trait BufRead: Io {
37+
/// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
38+
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error>;
39+
40+
/// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
41+
fn consume(&mut self, amt: usize);
42+
}
43+
44+
/// Async writer.
45+
///
46+
/// Semantics are the same as [`std::io::Write`], check its documentation for details.
47+
pub trait Write: Io {
48+
/// Write a buffer into this writer, returning how many bytes were written.
49+
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
50+
51+
/// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
52+
async fn flush(&mut self) -> Result<(), Self::Error> {
53+
Ok(())
54+
}
55+
56+
/// Write an entire buffer into this writer.
57+
async fn write_all(&mut self, buf: &[u8]) -> Result<(), WriteAllError<Self::Error>> {
58+
let mut buf = buf;
59+
while !buf.is_empty() {
60+
match self.write(buf).await {
61+
Ok(0) => return Err(WriteAllError::WriteZero),
62+
Ok(n) => buf = &buf[n..],
63+
Err(e) => return Err(WriteAllError::Other(e)),
64+
}
65+
}
66+
Ok(())
67+
}
68+
}
69+
70+
/// Async seek within streams.
71+
///
72+
/// Semantics are the same as [`std::io::Seek`], check its documentation for details.
73+
pub trait Seek: Io {
74+
/// Seek to an offset, in bytes, in a stream.
75+
async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error>;
76+
77+
/// Rewind to the beginning of a stream.
78+
async fn rewind(&mut self) -> Result<(), Self::Error> {
79+
self.seek(SeekFrom::Start(0)).await?;
80+
Ok(())
81+
}
82+
83+
/// Returns the current seek position from the start of the stream.
84+
async fn stream_position(&mut self) -> Result<u64, Self::Error> {
85+
self.seek(SeekFrom::Current(0)).await
86+
}
87+
}
88+
89+
impl<T: ?Sized + Read> Read for &mut T {
90+
#[inline]
91+
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
92+
T::read(self, buf).await
93+
}
94+
}
95+
96+
impl<T: ?Sized + BufRead> BufRead for &mut T {
97+
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
98+
T::fill_buf(self).await
99+
}
100+
101+
fn consume(&mut self, amt: usize) {
102+
T::consume(self, amt)
103+
}
104+
}
105+
106+
impl<T: ?Sized + Write> Write for &mut T {
107+
#[inline]
108+
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
109+
T::write(self, buf).await
110+
}
111+
112+
#[inline]
113+
async fn flush(&mut self) -> Result<(), Self::Error> {
114+
T::flush(self).await
115+
}
116+
}
117+
118+
impl<T: ?Sized + Seek> Seek for &mut T {
119+
#[inline]
120+
async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
121+
T::seek(self, pos).await
122+
}
123+
}

0 commit comments

Comments
 (0)