use core::fmt::{Arguments, Debug};
use std::ffi;
use std::io;
use crate::{Flush, IntoTryWriteFn, WriteBytes, WriteStr};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct IoTryWriter<F1, F2>(F1, F2);
pub trait IntoIoWriteResult {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize>;
}
pub trait IntoIoFlushResult {
fn into_io_flush_result(self) -> io::Result<()>;
}
impl<F1, F2> IoTryWriter<F1, F2>
where
F1: WriteStr,
F2: Flush,
{
pub fn new(write: F1, flush: F2) -> Self {
Self(write, flush)
}
}
impl<F1> IoTryWriter<F1, ()>
where
F1: WriteStr,
{
pub fn from_closure<F, Ts>(closure: F) -> Self
where
F: IntoTryWriteFn<Ts, TryWriteFn = F1>,
{
Self(closure.into_try_write_fn(), ())
}
}
impl<F1> IoTryWriter<F1, ()>
where
Self: io::Write,
{
pub fn write_fmt(&mut self, args: Arguments<'_>) -> io::Result<()> {
io::Write::write_fmt(self, args)
}
}
impl<F1, F2> io::Write for IoTryWriter<F1, F2>
where
Self: WriteBytes<Output = io::Result<usize>> + Flush<Output = io::Result<()>>,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
WriteBytes::write_bytes(self, buf)
}
fn flush(&mut self) -> io::Result<()> {
Flush::flush(self)
}
}
impl<F1, F2> WriteBytes for IoTryWriter<F1, F2>
where
F1: WriteBytes,
F1::Output: IntoIoWriteResult,
{
type Output = io::Result<usize>;
fn write_bytes(&mut self, buf: &[u8]) -> Self::Output {
self.0.write_bytes(buf).into_io_write_result(buf)
}
}
impl<F1, F2> Flush for IoTryWriter<F1, F2>
where
F2: Flush,
F2::Output: IntoIoFlushResult,
{
type Output = io::Result<()>;
fn flush(&mut self) -> Self::Output {
self.1.flush().into_io_flush_result()
}
}
impl IntoIoWriteResult for () {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}
}
impl IntoIoWriteResult for usize {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
let _ = buf;
Ok(self)
}
}
impl IntoIoWriteResult for Result<(), ffi::NulError> {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
self.map_or_else(
|err| Err(io::Error::new(io::ErrorKind::InvalidData, err)),
|_| Ok(buf.len()),
)
}
}
impl IntoIoWriteResult for Result<usize, ffi::NulError> {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
let _ = buf;
self.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
}
}
impl IntoIoWriteResult for io::Result<()> {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
self.map(|_| buf.len())
}
}
impl IntoIoWriteResult for io::Result<usize> {
fn into_io_write_result(self, buf: &[u8]) -> io::Result<usize> {
let _ = buf;
self
}
}
impl IntoIoFlushResult for () {
fn into_io_flush_result(self) -> io::Result<()> {
Ok(())
}
}
impl IntoIoFlushResult for io::Result<()> {
fn into_io_flush_result(self) -> io::Result<()> {
self
}
}