#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_docs)] #![doc = include_str!("../README.md")] // disable warning for already-stabilized features. // Needed to pass CI, because we deny warnings. // We don't immediately remove them to not immediately break older nightlies. // When all features are stable, we'll remove them. #![cfg_attr(nightly, allow(stable_features, unknown_lints))] #![cfg_attr(nightly, feature(async_fn_in_trait, impl_trait_projections))] #![allow(async_fn_in_trait)] #[cfg(feature = "alloc")] extern crate alloc; mod impls; pub use embedded_io::{ Error, ErrorKind, ErrorType, ReadExactError, ReadReady, SeekFrom, WriteReady, }; /// Async reader. /// /// This trait is the `embedded-io-async` equivalent of [`std::io::Read`]. pub trait Read: ErrorType { /// Read some bytes from this source into the specified buffer, returning how many bytes were read. /// /// If no bytes are currently available to read, this function waits until at least one byte is available. /// /// If bytes are available, a non-zero amount of bytes is read to the beginning of `buf`, and the amount /// is returned. It is not guaranteed that *all* available bytes are returned, it is possible for the /// implementation to read an amount of bytes less than `buf.len()` while there are more bytes immediately /// available. /// /// If the reader is at end-of-file (EOF), `Ok(0)` is returned. There is no guarantee that a reader at EOF /// will always be so in the future, for example a reader can stop being at EOF if another process appends /// more bytes to the underlying file. /// /// If `buf.len() == 0`, `read` returns without waiting, with either `Ok(0)` or an error. /// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer. /// /// Implementations are encouraged to make this function side-effect-free on cancel (AKA "cancel-safe"), i.e. /// guarantee that if you cancel (drop) a `read()` future that hasn't completed yet, the stream's /// state hasn't changed (no bytes have been read). /// /// This is not a requirement to allow implementations that read into the user's buffer straight from /// the hardware with e.g. DMA. /// /// Implementations should document whether they're actually side-effect-free on cancel or not. async fn read(&mut self, buf: &mut [u8]) -> Result; /// Read the exact number of bytes required to fill `buf`. /// /// This function calls `read()` in a loop until exactly `buf.len()` bytes have /// been read, waiting if needed. /// /// This function is not side-effect-free on cancel (AKA "cancel-safe"), i.e. if you cancel (drop) a returned /// future that hasn't completed yet, some bytes might have already been read, which will get lost. async fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError> { while !buf.is_empty() { match self.read(buf).await { Ok(0) => break, Ok(n) => buf = &mut buf[n..], Err(e) => return Err(ReadExactError::Other(e)), } } if buf.is_empty() { Ok(()) } else { Err(ReadExactError::UnexpectedEof) } } } /// Async buffered reader. /// /// This trait is the `embedded-io-async` equivalent of [`std::io::BufRead`]. pub trait BufRead: ErrorType { /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. /// /// If no bytes are currently available to read, this function waits until at least one byte is available. /// /// If the reader is at end-of-file (EOF), an empty slice is returned. There is no guarantee that a reader at EOF /// will always be so in the future, for example a reader can stop being at EOF if another process appends /// more bytes to the underlying file. async fn fill_buf(&mut self) -> Result<&[u8], Self::Error>; /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. fn consume(&mut self, amt: usize); } /// Async writer. /// /// This trait is the `embedded-io-async` equivalent of [`std::io::Write`]. pub trait Write: ErrorType { /// Write a buffer into this writer, returning how many bytes were written. /// /// If the writer is not currently ready to accept more bytes (for example, its buffer is full), /// this function waits until it is ready to accept least one byte. /// /// If it's ready to accept bytes, a non-zero amount of bytes is written from the beginning of `buf`, and the amount /// is returned. It is not guaranteed that *all* available buffer space is filled, i.e. it is possible for the /// implementation to write an amount of bytes less than `buf.len()` while the writer continues to be /// ready to accept more bytes immediately. /// /// Implementations should never return `Ok(0)` when `buf.len() != 0`. Situations where the writer is not /// able to accept more bytes and likely never will are better indicated with errors. /// /// If `buf.len() == 0`, `write` returns without waiting, with either `Ok(0)` or an error. /// The `Ok(0)` doesn't indicate an error. /// /// Implementations are encouraged to make this function side-effect-free on cancel (AKA "cancel-safe"), i.e. /// guarantee that if you cancel (drop) a `write()` future that hasn't completed yet, the stream's /// state hasn't changed (no bytes have been written). /// /// This is not a requirement to allow implementations that write from the user's buffer straight to /// the hardware with e.g. DMA. /// /// Implementations should document whether they're actually side-effect-free on cancel or not. async fn write(&mut self, buf: &[u8]) -> Result; /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. async fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } /// Write an entire buffer into this writer. /// /// This function calls `write()` in a loop until exactly `buf.len()` bytes have /// been written, waiting if needed. /// /// This function is not side-effect-free on cancel (AKA "cancel-safe"), i.e. if you cancel (drop) a returned /// future that hasn't completed yet, some bytes might have already been written. async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { let mut buf = buf; while !buf.is_empty() { match self.write(buf).await { Ok(0) => panic!("write() returned Ok(0)"), Ok(n) => buf = &buf[n..], Err(e) => return Err(e), } } Ok(()) } } /// Async seek within streams. /// /// This trait is the `embedded-io-async` equivalent of [`std::io::Seek`]. pub trait Seek: ErrorType { /// Seek to an offset, in bytes, in a stream. async fn seek(&mut self, pos: SeekFrom) -> Result; /// Rewind to the beginning of a stream. async fn rewind(&mut self) -> Result<(), Self::Error> { self.seek(SeekFrom::Start(0)).await?; Ok(()) } /// Returns the current seek position from the start of the stream. async fn stream_position(&mut self) -> Result { self.seek(SeekFrom::Current(0)).await } } impl Read for &mut T { #[inline] async fn read(&mut self, buf: &mut [u8]) -> Result { T::read(self, buf).await } } impl BufRead for &mut T { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { T::fill_buf(self).await } fn consume(&mut self, amt: usize) { T::consume(self, amt); } } impl Write for &mut T { #[inline] async fn write(&mut self, buf: &[u8]) -> Result { T::write(self, buf).await } #[inline] async fn flush(&mut self) -> Result<(), Self::Error> { T::flush(self).await } } impl Seek for &mut T { #[inline] async fn seek(&mut self, pos: SeekFrom) -> Result { T::seek(self, pos).await } }