embedded_io_async/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![warn(missing_docs)]
4#![doc = include_str!("../README.md")]
5#![allow(async_fn_in_trait)]
6
7#[cfg(feature = "alloc")]
8extern crate alloc;
9
10mod impls;
11
12pub use embedded_io::{
13    Error, ErrorKind, ErrorType, ReadExactError, ReadReady, SeekFrom, WriteReady,
14};
15
16/// Async reader.
17///
18/// This trait is the `embedded-io-async` equivalent of [`std::io::Read`].
19pub trait Read: ErrorType {
20    /// Read some bytes from this source into the specified buffer, returning how many bytes were read.
21    ///
22    /// If no bytes are currently available to read:
23    /// - The method waits until at least one byte becomes available;
24    /// - Once at least one (or more) bytes become available, a non-zero amount of those is copied to the
25    ///   beginning of `buf`, and the amount is returned, *without waiting any further for more bytes to
26    ///   become available*.
27    ///
28    /// If bytes are available to read:
29    /// - A non-zero amount of bytes is read to the beginning of `buf`, and the amount is returned immediately,
30    ///   *without waiting for more bytes to become available*;
31    ///
32    /// Note that once some bytes are available to read, it is *not* guaranteed that all available bytes are returned.
33    /// It is possible for the implementation to read an amount of bytes less than `buf.len()` while there are more
34    /// bytes immediately available.
35    ///
36    /// This waiting behavior is important for the cases where `Read` represents the "read" leg of a pipe-like
37    /// protocol (a socket, a pipe, a serial line etc.). The semantics is that the caller - by passing a non-empty
38    /// buffer - does expect _some_ data (one or more bytes) - but _not necessarily `buf.len()` or more bytes_ -
39    /// to become available, before the peer represented by `Read` would stop sending bytes due to
40    /// application-specific reasons (as in the peer waiting for a response to the data it had sent so far).
41    ///
42    /// If the reader is at end-of-file (EOF), `Ok(0)` is returned. There is no guarantee that a reader at EOF
43    /// will always be so in the future, for example a reader can stop being at EOF if another process appends
44    /// more bytes to the underlying file.
45    ///
46    /// If `buf.len() == 0`, `read` returns without waiting, with either `Ok(0)` or an error.
47    /// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer.
48    ///
49    /// Implementations are encouraged to make this function side-effect-free on cancel (AKA "cancel-safe"), i.e.
50    /// guarantee that if you cancel (drop) a `read()` future that hasn't completed yet, the stream's
51    /// state hasn't changed (no bytes have been read).
52    ///
53    /// This is not a requirement to allow implementations that read into the user's buffer straight from
54    /// the hardware with e.g. DMA.
55    ///
56    /// Implementations should document whether they're actually side-effect-free on cancel or not.
57    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
58
59    /// Read the exact number of bytes required to fill `buf`.
60    ///
61    /// This function calls `read()` in a loop until exactly `buf.len()` bytes have
62    /// been read, waiting if needed.
63    ///
64    /// This function is not side-effect-free on cancel (AKA "cancel-safe"), i.e. if you cancel (drop) a returned
65    /// future that hasn't completed yet, some bytes might have already been read, which will get lost.
66    async fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
67        while !buf.is_empty() {
68            match self.read(buf).await {
69                Ok(0) => break,
70                Ok(n) => buf = &mut buf[n..],
71                Err(e) => return Err(ReadExactError::Other(e)),
72            }
73        }
74        if buf.is_empty() {
75            Ok(())
76        } else {
77            Err(ReadExactError::UnexpectedEof)
78        }
79    }
80}
81
82/// Async buffered reader.
83///
84/// This trait is the `embedded-io-async` equivalent of [`std::io::BufRead`].
85pub trait BufRead: Read {
86    /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
87    ///
88    /// If no bytes are currently available to read, this function waits until at least one byte is available.
89    ///
90    /// If the reader is at end-of-file (EOF), an empty slice is returned. There is no guarantee that a reader at EOF
91    /// will always be so in the future, for example a reader can stop being at EOF if another process appends
92    /// more bytes to the underlying file.
93    async fn fill_buf(&mut self) -> Result<&[u8], Self::Error>;
94
95    /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
96    fn consume(&mut self, amt: usize);
97}
98
99/// Async writer.
100///
101/// This trait is the `embedded-io-async` equivalent of [`std::io::Write`].
102pub trait Write: ErrorType {
103    /// Write a buffer into this writer, returning how many bytes were written.
104    ///
105    /// If the writer is not currently ready to accept more bytes (for example, its buffer is full),
106    /// this function waits until it is ready to accept least one byte.
107    ///
108    /// If it's ready to accept bytes, a non-zero amount of bytes is written from the beginning of `buf`, and the amount
109    /// is returned. It is not guaranteed that *all* available buffer space is filled, i.e. it is possible for the
110    /// implementation to write an amount of bytes less than `buf.len()` while the writer continues to be
111    /// ready to accept more bytes immediately.
112    ///
113    /// Implementations should never return `Ok(0)` when `buf.len() != 0`. Situations where the writer is not
114    /// able to accept more bytes and likely never will are better indicated with errors.
115    ///
116    /// If `buf.len() == 0`, `write` returns without waiting, with either `Ok(0)` or an error.
117    /// The `Ok(0)` doesn't indicate an error.
118    ///
119    /// Implementations are encouraged to make this function side-effect-free on cancel (AKA "cancel-safe"), i.e.
120    /// guarantee that if you cancel (drop) a `write()` future that hasn't completed yet, the stream's
121    /// state hasn't changed (no bytes have been written).
122    ///
123    /// This is not a requirement to allow implementations that write from the user's buffer straight to
124    /// the hardware with e.g. DMA.
125    ///
126    /// Implementations should document whether they're actually side-effect-free on cancel or not.
127    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
128
129    /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
130    async fn flush(&mut self) -> Result<(), Self::Error>;
131
132    /// Write an entire buffer into this writer.
133    ///
134    /// This function calls `write()` in a loop until exactly `buf.len()` bytes have
135    /// been written, waiting if needed.
136    ///
137    /// This function is not side-effect-free on cancel (AKA "cancel-safe"), i.e. if you cancel (drop) a returned
138    /// future that hasn't completed yet, some bytes might have already been written.
139    async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
140        let mut buf = buf;
141        while !buf.is_empty() {
142            match self.write(buf).await {
143                Ok(0) => panic!("write() returned Ok(0)"),
144                Ok(n) => buf = &buf[n..],
145                Err(e) => return Err(e),
146            }
147        }
148        Ok(())
149    }
150}
151
152/// Async seek within streams.
153///
154/// This trait is the `embedded-io-async` equivalent of [`std::io::Seek`].
155pub trait Seek: ErrorType {
156    /// Seek to an offset, in bytes, in a stream.
157    async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error>;
158
159    /// Rewind to the beginning of a stream.
160    async fn rewind(&mut self) -> Result<(), Self::Error> {
161        self.seek(SeekFrom::Start(0)).await?;
162        Ok(())
163    }
164
165    /// Returns the current seek position from the start of the stream.
166    async fn stream_position(&mut self) -> Result<u64, Self::Error> {
167        self.seek(SeekFrom::Current(0)).await
168    }
169}
170
171impl<T: ?Sized + Read> Read for &mut T {
172    #[inline]
173    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
174        T::read(self, buf).await
175    }
176
177    #[inline]
178    async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
179        T::read_exact(self, buf).await
180    }
181}
182
183impl<T: ?Sized + BufRead> BufRead for &mut T {
184    #[inline]
185    async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
186        T::fill_buf(self).await
187    }
188
189    #[inline]
190    fn consume(&mut self, amt: usize) {
191        T::consume(self, amt);
192    }
193}
194
195impl<T: ?Sized + Write> Write for &mut T {
196    #[inline]
197    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
198        T::write(self, buf).await
199    }
200
201    #[inline]
202    async fn flush(&mut self) -> Result<(), Self::Error> {
203        T::flush(self).await
204    }
205
206    #[inline]
207    async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
208        T::write_all(self, buf).await
209    }
210}
211
212impl<T: ?Sized + Seek> Seek for &mut T {
213    #[inline]
214    async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
215        T::seek(self, pos).await
216    }
217
218    #[inline]
219    async fn rewind(&mut self) -> Result<(), Self::Error> {
220        T::rewind(self).await
221    }
222
223    #[inline]
224    async fn stream_position(&mut self) -> Result<u64, Self::Error> {
225        T::stream_position(self).await
226    }
227}