Skip to content

Commit cb4f7a4

Browse files
authored
Merge pull request #697 from hermit-os/io-vec_deque
feat(io): implement `Read`, `ReadReady`, `BufRead`, `Write`, and `WriteReady` for `VecDeque<u8>`
2 parents 8c2b548 + ad6a7d1 commit cb4f7a4

File tree

5 files changed

+194
-1
lines changed

5 files changed

+194
-1
lines changed

embedded-io-async/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "embedded-io-async"
33
version = "0.6.1"
44
edition = "2021"
5-
rust-version = "1.75"
5+
rust-version = "1.81"
66
description = "Async embedded IO traits"
77
repository = "https://github.com/rust-embedded/embedded-hal"
88
readme = "README.md"

embedded-io-async/src/impls/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ mod slice_ref;
55
mod boxx;
66
#[cfg(feature = "alloc")]
77
mod vec;
8+
#[cfg(feature = "alloc")]
9+
mod vec_deque;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Adapted from std.
2+
3+
use alloc::collections::vec_deque::VecDeque;
4+
5+
use crate::{BufRead, Read, ReadExactError, Write};
6+
7+
/// Read is implemented for `VecDeque<u8>` by consuming bytes from the front of the `VecDeque`.
8+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
9+
impl Read for VecDeque<u8> {
10+
/// Fill `buf` with the contents of the "front" slice as returned by
11+
/// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
12+
/// discontiguous, multiple calls to `read` will be needed to read the entire content.
13+
#[inline]
14+
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
15+
let (ref mut front, _) = self.as_slices();
16+
let n = Read::read(front, buf).await?;
17+
self.drain(..n);
18+
Ok(n)
19+
}
20+
21+
#[inline]
22+
async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
23+
let (front, back) = self.as_slices();
24+
25+
// Use only the front buffer if it is big enough to fill `buf`, else use
26+
// the back buffer too.
27+
match buf.split_at_mut_checked(front.len()) {
28+
None => buf.copy_from_slice(&front[..buf.len()]),
29+
Some((buf_front, buf_back)) => match back.split_at_checked(buf_back.len()) {
30+
Some((back, _)) => {
31+
buf_front.copy_from_slice(front);
32+
buf_back.copy_from_slice(back);
33+
}
34+
None => {
35+
self.clear();
36+
return Err(ReadExactError::UnexpectedEof);
37+
}
38+
},
39+
}
40+
41+
self.drain(..buf.len());
42+
Ok(())
43+
}
44+
}
45+
46+
/// BufRead is implemented for `VecDeque<u8>` by reading bytes from the front of the `VecDeque`.
47+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
48+
impl BufRead for VecDeque<u8> {
49+
/// Returns the contents of the "front" slice as returned by
50+
/// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
51+
/// discontiguous, multiple calls to `fill_buf` will be needed to read the entire content.
52+
#[inline]
53+
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
54+
let (front, _) = self.as_slices();
55+
Ok(front)
56+
}
57+
58+
#[inline]
59+
fn consume(&mut self, amt: usize) {
60+
self.drain(..amt);
61+
}
62+
}
63+
64+
/// Write is implemented for `VecDeque<u8>` by appending to the `VecDeque`, growing it as needed.
65+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
66+
impl Write for VecDeque<u8> {
67+
#[inline]
68+
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
69+
self.extend(buf);
70+
Ok(buf.len())
71+
}
72+
73+
#[inline]
74+
async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
75+
self.extend(buf);
76+
Ok(())
77+
}
78+
79+
#[inline]
80+
async fn flush(&mut self) -> Result<(), Self::Error> {
81+
Ok(())
82+
}
83+
}

embedded-io/src/impls/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ mod slice_ref;
55
mod boxx;
66
#[cfg(feature = "alloc")]
77
mod vec;
8+
#[cfg(feature = "alloc")]
9+
mod vec_deque;

embedded-io/src/impls/vec_deque.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//! Adapted from std.
2+
3+
use core::convert::Infallible;
4+
5+
use alloc::collections::vec_deque::VecDeque;
6+
7+
use crate::{BufRead, ErrorType, Read, ReadExactError, ReadReady, Write, WriteReady};
8+
9+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
10+
impl ErrorType for VecDeque<u8> {
11+
type Error = Infallible;
12+
}
13+
14+
/// Read is implemented for `VecDeque<u8>` by consuming bytes from the front of the `VecDeque`.
15+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
16+
impl Read for VecDeque<u8> {
17+
/// Fill `buf` with the contents of the "front" slice as returned by
18+
/// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
19+
/// discontiguous, multiple calls to `read` will be needed to read the entire content.
20+
#[inline]
21+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
22+
let (ref mut front, _) = self.as_slices();
23+
let n = Read::read(front, buf)?;
24+
self.drain(..n);
25+
Ok(n)
26+
}
27+
28+
#[inline]
29+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
30+
let (front, back) = self.as_slices();
31+
32+
// Use only the front buffer if it is big enough to fill `buf`, else use
33+
// the back buffer too.
34+
match buf.split_at_mut_checked(front.len()) {
35+
None => buf.copy_from_slice(&front[..buf.len()]),
36+
Some((buf_front, buf_back)) => match back.split_at_checked(buf_back.len()) {
37+
Some((back, _)) => {
38+
buf_front.copy_from_slice(front);
39+
buf_back.copy_from_slice(back);
40+
}
41+
None => {
42+
self.clear();
43+
return Err(ReadExactError::UnexpectedEof);
44+
}
45+
},
46+
}
47+
48+
self.drain(..buf.len());
49+
Ok(())
50+
}
51+
}
52+
53+
/// BufRead is implemented for `VecDeque<u8>` by reading bytes from the front of the `VecDeque`.
54+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
55+
impl BufRead for VecDeque<u8> {
56+
/// Returns the contents of the "front" slice as returned by
57+
/// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
58+
/// discontiguous, multiple calls to `fill_buf` will be needed to read the entire content.
59+
#[inline]
60+
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
61+
let (front, _) = self.as_slices();
62+
Ok(front)
63+
}
64+
65+
#[inline]
66+
fn consume(&mut self, amt: usize) {
67+
self.drain(..amt);
68+
}
69+
}
70+
71+
/// Write is implemented for `VecDeque<u8>` by appending to the `VecDeque`, growing it as needed.
72+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
73+
impl Write for VecDeque<u8> {
74+
#[inline]
75+
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
76+
self.extend(buf);
77+
Ok(buf.len())
78+
}
79+
80+
#[inline]
81+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
82+
self.extend(buf);
83+
Ok(())
84+
}
85+
86+
#[inline]
87+
fn flush(&mut self) -> Result<(), Self::Error> {
88+
Ok(())
89+
}
90+
}
91+
92+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
93+
impl ReadReady for VecDeque<u8> {
94+
#[inline]
95+
fn read_ready(&mut self) -> Result<bool, Self::Error> {
96+
Ok(true)
97+
}
98+
}
99+
100+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
101+
impl WriteReady for VecDeque<u8> {
102+
#[inline]
103+
fn write_ready(&mut self) -> Result<bool, Self::Error> {
104+
Ok(true)
105+
}
106+
}

0 commit comments

Comments
 (0)