This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/embedded-io-async/src/lib.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

201 lines
8.3 KiB
Rust

#![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<usize, Self::Error>;
/// 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<Self::Error>> {
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<usize, Self::Error>;
/// 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<u64, Self::Error>;
/// 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<u64, Self::Error> {
self.seek(SeekFrom::Current(0)).await
}
}
impl<T: ?Sized + Read> Read for &mut T {
#[inline]
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
T::read(self, buf).await
}
}
impl<T: ?Sized + BufRead> 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<T: ?Sized + Write> Write for &mut T {
#[inline]
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
T::write(self, buf).await
}
#[inline]
async fn flush(&mut self) -> Result<(), Self::Error> {
T::flush(self).await
}
}
impl<T: ?Sized + Seek> Seek for &mut T {
#[inline]
async fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
T::seek(self, pos).await
}
}