#[cfg(feature = "alloc")] use alloc::boxed::Box; use internals::rust_version; /// A bridging wrapper providing the IO traits for types that already implement `std` IO traits. #[repr(transparent)] pub struct FromStd(T); impl FromStd { /// Wraps an IO type. #[inline] pub const fn new(inner: T) -> Self { Self(inner) } /// Wraps a mutable reference to IO type. #[inline] pub fn new_mut(inner: &mut T) -> &mut Self { // SAFETY: the type is repr(transparent) and the lifetimes match unsafe { &mut *(inner as *mut _ as *mut Self) } } /// Wraps a boxed IO type. #[cfg(feature = "alloc")] #[inline] pub fn new_boxed(inner: Box) -> Box { // SAFETY: the type is repr(transparent) and the pointer is created from Box unsafe { Box::from_raw(Box::into_raw(inner) as *mut Self) } } /// Returns the wrapped value. #[inline] pub fn into_inner(self) -> T { self.0 } /// Returns a reference to the wrapped value. #[inline] pub fn inner(&self) -> &T { &self.0 } /// Returns a mutable reference to the wrapped value. #[inline] pub fn inner_mut(&mut self) -> &mut T { &mut self.0 } } impl super::Read for FromStd { #[inline] fn read(&mut self, buf: &mut [u8]) -> super::Result { self.0.read(buf).map_err(Into::into) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { self.0.read_exact(buf).map_err(Into::into) } } impl super::BufRead for FromStd { #[inline] fn fill_buf(&mut self) -> super::Result<&[u8]> { self.0.fill_buf().map_err(Into::into) } #[inline] fn consume(&mut self, amount: usize) { self.0.consume(amount) } } impl super::Write for FromStd { #[inline] fn write(&mut self, buf: &[u8]) -> super::Result { self.0.write(buf).map_err(Into::into) } #[inline] fn flush(&mut self) -> super::Result<()> { self.0.flush().map_err(Into::into) } #[inline] fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { self.0.write_all(buf).map_err(Into::into) } } // We also impl std traits so that mixing the calls is not annoying. impl std::io::Read for FromStd { #[inline] fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.0.read(buf) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { self.0.read_exact(buf) } } impl std::io::BufRead for FromStd { #[inline] fn fill_buf(&mut self) -> std::io::Result<&[u8]> { self.0.fill_buf() } #[inline] fn consume(&mut self, amount: usize) { self.0.consume(amount) } } impl std::io::Write for FromStd { #[inline] fn write(&mut self, buf: &[u8]) -> std::io::Result { self.0.write(buf) } #[inline] fn flush(&mut self) -> std::io::Result<()> { self.0.flush() } #[inline] fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { self.0.write_all(buf) } } /// A bridging wrapper providing the std traits for types that already implement our traits. #[repr(transparent)] pub struct ToStd(T); impl ToStd { /// Wraps an IO type. #[inline] pub const fn new(inner: T) -> Self { Self(inner) } /// Returns the wrapped value. #[inline] pub fn into_inner(self) -> T { self.0 } /// Returns a reference to the wrapped value. #[inline] pub fn inner(&self) -> &T { &self.0 } /// Returns a mutable reference to the wrapped value. #[inline] pub fn inner_mut(&mut self) -> &mut T { &mut self.0 } /// Wraps a mutable reference to IO type. #[inline] pub fn new_mut(inner: &mut T) -> &mut Self { // SAFETY: the type is repr(transparent) and the lifetimes match unsafe { &mut *(inner as *mut _ as *mut Self) } } /// Wraps a boxed IO type. #[cfg(feature = "alloc")] #[inline] pub fn new_boxed(inner: Box) -> Box { // SAFETY: the type is repr(transparent) and the pointer is created from Box unsafe { Box::from_raw(Box::into_raw(inner) as *mut Self) } } } impl std::io::Read for ToStd { #[inline] fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.0.read(buf).map_err(Into::into) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { self.0.read_exact(buf).map_err(Into::into) } } impl std::io::BufRead for ToStd { #[inline] fn fill_buf(&mut self) -> std::io::Result<&[u8]> { self.0.fill_buf().map_err(Into::into) } #[inline] fn consume(&mut self, amount: usize) { self.0.consume(amount) } } impl std::io::Write for ToStd { #[inline] fn write(&mut self, buf: &[u8]) -> std::io::Result { self.0.write(buf).map_err(Into::into) } #[inline] fn flush(&mut self) -> std::io::Result<()> { self.0.flush().map_err(Into::into) } #[inline] fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { self.0.write_all(buf).map_err(Into::into) } } // We also impl our traits so that mixing the calls is not annoying. impl super::Read for ToStd { #[inline] fn read(&mut self, buf: &mut [u8]) -> super::Result { self.0.read(buf) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { self.0.read_exact(buf) } } impl super::BufRead for ToStd { #[inline] fn fill_buf(&mut self) -> super::Result<&[u8]> { self.0.fill_buf() } #[inline] fn consume(&mut self, amount: usize) { self.0.consume(amount) } } impl super::Write for ToStd { #[inline] fn write(&mut self, buf: &[u8]) -> super::Result { self.0.write(buf) } #[inline] fn flush(&mut self) -> super::Result<()> { self.0.flush() } #[inline] fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { self.0.write_all(buf) } } macro_rules! impl_our { (impl$(<$($gen:ident $(: $gent:path)?),*>)? Read for $std_type:ty $(where $($where:tt)*)?) => { impl$(<$($gen$(: $gent)?),*>)? super::Read for $std_type $(where $($where)*)? { #[inline] fn read(&mut self, buf: &mut [u8]) -> super::Result { std::io::Read::read(self, buf).map_err(Into::into) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { std::io::Read::read_exact(self, buf).map_err(Into::into) } } }; (impl$(<$($gen:ident $(: $gent:path)?),*>)? BufRead for $std_type:ty $(where $($where:tt)*)?) => { impl$(<$($gen$(: $gent)?),*>)? super::BufRead for $std_type $(where $($where)*)? { #[inline] fn fill_buf(&mut self) -> super::Result<&[u8]> { std::io::BufRead::fill_buf(self).map_err(Into::into) } #[inline] fn consume(&mut self, amount: usize) { std::io::BufRead::consume(self, amount) } } }; (impl$(<$($gen:ident $(: $gent:path)?),*>)? Write for $std_type:ty $(where $($where:tt)*)?) => { impl$(<$($gen$(: $gent)?),*>)? super::Write for $std_type $(where $($where)*)? { #[inline] fn write(&mut self, buf: &[u8]) -> super::Result { std::io::Write::write(self, buf).map_err(Into::into) } #[inline] fn flush(&mut self) -> super::Result<()> { std::io::Write::flush(self).map_err(Into::into) } #[inline] fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { std::io::Write::write_all(self, buf).map_err(Into::into) } } }; } rust_version! { if >= 1.72 { impl_our! { impl Read for std::io::BufReader where R: ?Sized } impl_our! { impl BufRead for std::io::BufReader where R: ?Sized } impl_our! { impl Write for std::io::BufWriter where W: ?Sized } impl_our! { impl Write for std::io::LineWriter where W: ?Sized } } else { impl_our! { impl Read for std::io::BufReader } impl_our! { impl BufRead for std::io::BufReader } impl_our! { impl Write for std::io::BufWriter } impl_our! { impl Write for std::io::LineWriter } } } impl std::io::Write for super::Sink { #[inline] fn write(&mut self, buf: &[u8]) -> std::io::Result { Ok(buf.len()) } #[inline] fn write_all(&mut self, _: &[u8]) -> std::io::Result<()> { Ok(()) } #[inline] fn flush(&mut self) -> std::io::Result<()> { Ok(()) } } impl_our! { impl Read for std::io::Take } impl_our! { impl BufRead for std::io::Take } impl_our! { impl Read for std::io::Chain } impl_our! { impl BufRead for std::io::Chain } impl_our! { impl> Read for std::io::Cursor } impl_our! { impl> BufRead for std::io::Cursor } impl_our! { impl Write for std::io::Cursor> } impl_our! { impl Write for std::io::Cursor<&'_ mut std::vec::Vec> } impl_our! { impl Write for std::io::Cursor> } impl_our! { impl Read for std::io::Empty } impl_our! { impl BufRead for std::io::Empty } rust_version! { if >= 1.73 { impl_our! { impl Write for std::io::Empty } // No idea why &Empty impls Write but not Read + BufRead impl_our! { impl Write for &'_ std::io::Empty } impl_our! { impl Read for std::sync::Arc } impl_our! { impl Write for std::sync::Arc } } } impl_our! { impl Read for std::io::Repeat } impl_our! { impl Read for std::io::Stdin } rust_version! { if >= 1.78 { impl_our! { impl Read for &'_ std::io::Stdin } } } impl_our! { impl Write for std::io::Stdout } impl_our! { impl Write for &'_ std::io::Stdout } impl_our! { impl Write for std::io::Stderr } impl_our! { impl Write for &'_ std::io::Stderr } impl_our! { impl Read for std::io::StdinLock<'_> } impl_our! { impl BufRead for std::io::StdinLock<'_> } impl_our! { impl Read for std::fs::File } impl_our! { impl Write for std::fs::File } impl_our! { impl Read for &'_ std::fs::File } impl_our! { impl Write for &'_ std::fs::File } impl_our! { impl Read for std::net::TcpStream } impl_our! { impl Write for std::net::TcpStream } impl_our! { impl Read for &'_ std::net::TcpStream } impl_our! { impl Write for &'_ std::net::TcpStream } #[cfg(target_family = "unix")] impl_our! { impl Read for std::os::unix::net::UnixStream } #[cfg(target_family = "unix")] impl_our! { impl Write for std::os::unix::net::UnixStream } #[cfg(target_family = "unix")] impl_our! { impl Read for &'_ std::os::unix::net::UnixStream } #[cfg(target_family = "unix")] impl_our! { impl Write for &'_ std::os::unix::net::UnixStream } impl_our! { impl Read for std::process::ChildStderr } impl_our! { impl Read for std::process::ChildStdout } impl_our! { impl Write for std::process::ChildStdin } // No ide why other &ChildStd* are not implemented impl_our! { impl Write for &'_ std::process::ChildStdin } rust_version! { if >= 1.75 { impl_our! { impl Read for std::collections::VecDeque } impl_our! { impl BufRead for std::collections::VecDeque } } } impl_our! { impl Write for std::collections::VecDeque }