Skip to content

Commit 1b5a858

Browse files
committed
io: add adapters to/from std::io.
1 parent eb6e078 commit 1b5a858

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

embedded-io/src/adapters.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//! Adapters to/from `std::io` traits.
2+
//!
3+
//! To interoperate with `std::io`, wrap a type in one of these
4+
//! adapters.
5+
//!
6+
//! There's no separate adapters for Read/ReadBuf/Write traits. Instead, a single
7+
//! adapter implements the right traits based on what the inner type implements.
8+
//! This allows adapting a `Read+Write`, for example.
9+
10+
use crate::SeekFrom;
11+
12+
/// Adapter from `std::io` traits.
13+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
14+
#[derive(Clone)]
15+
pub struct FromStd<T: ?Sized> {
16+
inner: T,
17+
}
18+
19+
impl<T> FromStd<T> {
20+
/// Create a new adapter.
21+
pub fn new(inner: T) -> Self {
22+
Self { inner }
23+
}
24+
25+
/// Consume the adapter, returning the inner object.
26+
pub fn into_inner(self) -> T {
27+
self.inner
28+
}
29+
}
30+
31+
impl<T: ?Sized> FromStd<T> {
32+
/// Borrow the inner object.
33+
pub fn inner(&self) -> &T {
34+
&self.inner
35+
}
36+
37+
/// Mutably borrow the inner object.
38+
pub fn inner_mut(&mut self) -> &mut T {
39+
&mut self.inner
40+
}
41+
}
42+
43+
impl<T: ?Sized> crate::Io for FromStd<T> {
44+
type Error = std::io::Error;
45+
}
46+
47+
impl<T: std::io::Read + ?Sized> crate::Read for FromStd<T> {
48+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
49+
self.inner.read(buf)
50+
}
51+
}
52+
53+
impl<T: std::io::BufRead + ?Sized> crate::BufRead for FromStd<T> {
54+
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
55+
self.inner.fill_buf()
56+
}
57+
58+
fn consume(&mut self, amt: usize) {
59+
self.inner.consume(amt)
60+
}
61+
}
62+
63+
impl<T: std::io::Write + ?Sized> crate::Write for FromStd<T> {
64+
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
65+
self.inner.write(buf)
66+
}
67+
fn flush(&mut self) -> Result<(), Self::Error> {
68+
self.inner.flush()
69+
}
70+
}
71+
72+
impl<T: std::io::Seek + ?Sized> crate::Seek for FromStd<T> {
73+
fn seek(&mut self, pos: crate::SeekFrom) -> Result<u64, Self::Error> {
74+
self.inner.seek(pos.into())
75+
}
76+
}
77+
78+
/// Adapter to `std::io` traits.
79+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
80+
pub struct ToStd<T: ?Sized> {
81+
inner: T,
82+
}
83+
84+
impl<T> ToStd<T> {
85+
/// Create a new adapter.
86+
pub fn new(inner: T) -> Self {
87+
Self { inner }
88+
}
89+
90+
/// Consume the adapter, returning the inner object.
91+
pub fn into_inner(self) -> T {
92+
self.inner
93+
}
94+
}
95+
96+
impl<T: ?Sized> ToStd<T> {
97+
/// Borrow the inner object.
98+
pub fn inner(&self) -> &T {
99+
&self.inner
100+
}
101+
102+
/// Mutably borrow the inner object.
103+
pub fn inner_mut(&mut self) -> &mut T {
104+
&mut self.inner
105+
}
106+
}
107+
108+
impl<T: crate::Read + ?Sized> std::io::Read for ToStd<T> {
109+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
110+
self.inner.read(buf).map_err(to_io_error)
111+
}
112+
}
113+
114+
impl<T: crate::Write + ?Sized> std::io::Write for ToStd<T> {
115+
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
116+
self.inner.write(buf).map_err(to_io_error)
117+
}
118+
fn flush(&mut self) -> Result<(), std::io::Error> {
119+
self.inner.flush().map_err(to_io_error)
120+
}
121+
}
122+
123+
impl<T: crate::Seek + ?Sized> std::io::Seek for ToStd<T> {
124+
fn seek(&mut self, pos: std::io::SeekFrom) -> Result<u64, std::io::Error> {
125+
self.inner.seek(pos.into()).map_err(to_io_error)
126+
}
127+
}
128+
129+
fn to_io_error<T: core::fmt::Debug>(err: T) -> std::io::Error {
130+
let kind = std::io::ErrorKind::Other;
131+
std::io::Error::new(kind, format!("{:?}", err))
132+
}
133+
134+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
135+
impl crate::Error for std::io::Error {
136+
fn kind(&self) -> crate::ErrorKind {
137+
crate::ErrorKind::Other
138+
}
139+
}
140+
141+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
142+
impl From<SeekFrom> for std::io::SeekFrom {
143+
fn from(pos: SeekFrom) -> Self {
144+
match pos {
145+
SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
146+
SeekFrom::End(n) => std::io::SeekFrom::End(n),
147+
SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
148+
}
149+
}
150+
}
151+
152+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
153+
impl From<std::io::SeekFrom> for SeekFrom {
154+
fn from(pos: std::io::SeekFrom) -> SeekFrom {
155+
match pos {
156+
std::io::SeekFrom::Start(n) => SeekFrom::Start(n),
157+
std::io::SeekFrom::End(n) => SeekFrom::End(n),
158+
std::io::SeekFrom::Current(n) => SeekFrom::Current(n),
159+
}
160+
}
161+
}

embedded-io/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use core::fmt;
88
#[cfg(feature = "alloc")]
99
extern crate alloc;
1010

11+
#[cfg(feature = "std")]
12+
pub mod adapters;
13+
1114
mod impls;
1215

1316
/// Enumeration of possible methods to seek within an I/O object.

0 commit comments

Comments
 (0)