diff --git a/embedded-io-async/src/impls/slice_mut.rs b/embedded-io-async/src/impls/slice_mut.rs index bd64d1320..57ff41fcd 100644 --- a/embedded-io-async/src/impls/slice_mut.rs +++ b/embedded-io-async/src/impls/slice_mut.rs @@ -1,4 +1,4 @@ -use core::mem; +use core::mem::{self, MaybeUninit}; use embedded_io::SliceWriteError; use crate::Write; @@ -20,7 +20,32 @@ impl Write for &mut [u8] { return Err(SliceWriteError::Full); } let (a, b) = mem::take(self).split_at_mut(amt); - a.copy_from_slice(&buf[..amt]); + a.copy_from_slice(buf.split_at(amt).0); + *self = b; + Ok(amt) + } +} + +/// Write is implemented for `&mut [MaybeUninit]` by copying into the slice, initializing +/// & overwriting its data. +/// +/// Note that writing updates the slice to point to the yet unwritten part. +/// The slice will be empty when it has been completely overwritten. +/// +/// If the number of bytes to be written exceeds the size of the slice, write operations will +/// return short writes: ultimately, `Ok(0)`; in this situation, `write_all` returns an error of +/// kind `ErrorKind::WriteZero`. +impl Write for &mut [MaybeUninit] { + #[inline] + async fn write(&mut self, buf: &[u8]) -> Result { + let amt = core::cmp::min(buf.len(), self.len()); + if !buf.is_empty() && amt == 0 { + return Err(SliceWriteError::Full); + } + let (a, b) = mem::take(self).split_at_mut(amt); + unsafe { + core::ptr::copy_nonoverlapping(buf.as_ptr(), a.as_mut_ptr() as *mut u8, amt); + } *self = b; Ok(amt) } diff --git a/embedded-io/src/impls/slice_mut.rs b/embedded-io/src/impls/slice_mut.rs index cee991ea6..8d27c9b76 100644 --- a/embedded-io/src/impls/slice_mut.rs +++ b/embedded-io/src/impls/slice_mut.rs @@ -1,5 +1,5 @@ use crate::{Error, ErrorKind, ErrorType, SliceWriteError, Write, WriteReady}; -use core::mem; +use core::mem::{self, MaybeUninit}; impl Error for SliceWriteError { fn kind(&self) -> ErrorKind { @@ -9,10 +9,6 @@ impl Error for SliceWriteError { } } -impl ErrorType for &mut [u8] { - type Error = SliceWriteError; -} - impl core::fmt::Display for SliceWriteError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{self:?}") @@ -21,6 +17,10 @@ impl core::fmt::Display for SliceWriteError { impl core::error::Error for SliceWriteError {} +impl ErrorType for &mut [u8] { + type Error = SliceWriteError; +} + /// Write is implemented for `&mut [u8]` by copying into the slice, overwriting /// its data. /// @@ -37,7 +37,7 @@ impl Write for &mut [u8] { return Err(SliceWriteError::Full); } let (a, b) = mem::take(self).split_at_mut(amt); - a.copy_from_slice(&buf[..amt]); + a.copy_from_slice(buf.split_at(amt).0); *self = b; Ok(amt) } @@ -54,3 +54,43 @@ impl WriteReady for &mut [u8] { Ok(true) } } + +impl ErrorType for &mut [MaybeUninit] { + type Error = SliceWriteError; +} + +/// Write is implemented for `&mut [MaybeUninit]` by copying into the slice, initializing +/// & overwriting its data. +/// +/// Note that writing updates the slice to point to the yet unwritten part. +/// The slice will be empty when it has been completely overwritten. +/// +/// If the number of bytes to be written exceeds the size of the slice, write operations will +/// return short writes: ultimately, a `SliceWriteError::Full`. +impl Write for &mut [MaybeUninit] { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + let amt = core::cmp::min(buf.len(), self.len()); + if !buf.is_empty() && amt == 0 { + return Err(SliceWriteError::Full); + } + let (a, b) = mem::take(self).split_at_mut(amt); + unsafe { + core::ptr::copy_nonoverlapping(buf.as_ptr(), a.as_mut_ptr() as *mut u8, amt); + } + *self = b; + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } +} + +impl WriteReady for &mut [MaybeUninit] { + #[inline] + fn write_ready(&mut self) -> Result { + Ok(true) + } +}