#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::{fmt, str};
use rusl::error::Errno;
use crate::error::{Error, Result};
#[cfg(feature = "alloc")]
pub(crate) mod read_buf;
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
#[cfg(feature = "alloc")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
default_read_to_end(self, buf)
}
#[cfg(feature = "alloc")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
default_read_to_string(self, buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
default_read_exact(self, buf)
}
fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
}
#[cfg(feature = "alloc")]
pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
let start_len = buf.len();
let start_cap = buf.capacity();
let mut initialized = 0; loop {
if buf.len() == buf.capacity() {
buf.reserve(32); }
let mut read_buf = crate::io::read_buf::ReadBuf::uninit(buf.spare_capacity_mut());
unsafe {
read_buf.assume_init(initialized);
}
match default_read_buf(|b| r.read(b), &mut read_buf) {
Ok(()) => {}
Err(ref e) if e.matches_errno(Errno::EINTR) => continue,
Err(e) => return Err(e),
}
if read_buf.filled_len() == 0 {
return Ok(buf.len() - start_len);
}
initialized = read_buf.initialized_len() - read_buf.filled_len();
let new_len = read_buf.filled_len() + buf.len();
unsafe {
buf.set_len(new_len);
}
if buf.len() == buf.capacity() && buf.capacity() == start_cap {
let mut probe = [0u8; 32];
loop {
match r.read(&mut probe) {
Ok(0) => return Ok(buf.len() - start_len),
Ok(n) => {
buf.extend_from_slice(&probe[..n]);
break;
}
Err(ref e) if e.matches_errno(Errno::EINTR) => {}
Err(e) => return Err(e),
}
}
}
}
}
#[cfg(feature = "alloc")]
pub(crate) fn default_read_to_string<R: Read + ?Sized>(
r: &mut R,
buf: &mut String,
) -> Result<usize> {
unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) }
}
#[cfg(feature = "alloc")]
pub(crate) unsafe fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
where
F: FnOnce(&mut Vec<u8>) -> Result<usize>,
{
struct Guard<'a> {
buf: &'a mut Vec<u8>,
len: usize,
}
impl Drop for Guard<'_> {
fn drop(&mut self) {
unsafe {
self.buf.set_len(self.len);
}
}
}
let mut g = Guard {
len: buf.len(),
buf: buf.as_mut_vec(),
};
let ret = f(g.buf);
if str::from_utf8(&g.buf[g.len..]).is_err() {
ret.and_then(|_| Err(Error::no_code("Stream did not contain valid UTF-8")))
} else {
g.len = g.buf.len();
ret
}
}
pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match this.read(buf) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.matches_errno(Errno::EINTR) => {}
Err(e) => return Err(e),
}
}
if buf.is_empty() {
Ok(())
} else {
Err(Error::no_code("Failed to fill whole buffer"))
}
}
#[cfg(feature = "alloc")]
pub(crate) fn default_read_buf<F>(read: F, buf: &mut crate::io::read_buf::ReadBuf<'_>) -> Result<()>
where
F: FnOnce(&mut [u8]) -> Result<usize>,
{
let n = read(buf.initialize_unfilled())?;
buf.add_filled(n);
Ok(())
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => {
return Err(Error::no_code("failed to write whole buffer"));
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.matches_errno(Errno::EINTR) => {}
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
struct Adapter<'a, T: ?Sized + 'a> {
inner: &'a mut T,
error: Result<()>,
}
impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
Err(e) => {
self.error = Err(e);
Err(fmt::Error)
}
}
}
}
let mut output = Adapter {
inner: self,
error: Ok(()),
};
match fmt::write(&mut output, fmt) {
Ok(()) => Ok(()),
Err(..) => {
if output.error.is_err() {
output.error
} else {
Err(Error::no_code("formatter error"))
}
}
}
}
fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
}