Skip to content

Commit 300c8b1

Browse files
committed
feat: implement Read, BufRead, and Write for VecDeque<u8>
1 parent e12dbf6 commit 300c8b1

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed

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: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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, Write};
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+
}

0 commit comments

Comments
 (0)