#[cfg(feature = "futures")]
mod futures_impl;
#[cfg(feature = "io-std")]
mod std_impl;
#[cfg(feature = "tokio")]
mod tokio_impl;

/// A writer that writes to two underlying writers, in sync
#[derive(Debug)]
pub struct TeeWriter<This, Other> {
    pub(crate) this: This,
    pub(crate) other: Other,
    pub(crate) offset: isize,
}

/// Extension trait to add `tee` method to any writer
///
/// # Example
/// ```rust
/// use teewriter::TeeWriterExt;
/// use std::io::Write;
/// let mut writer1 = Vec::new();
/// let mut writer2 = Vec::new();
/// let mut tee = writer1.tee(&mut writer2);
/// tee.write_all(b"Hello, world!").unwrap();
/// let (writer1, writer2, offset) = tee.into_inner();
/// if offset != 0 {
///    panic!("Writers are out of sync by {}", offset);
/// }
/// assert_eq!(writer1, b"Hello, world!");
/// assert_eq!(writer2, b"Hello, world!");
/// ```
pub trait TeeWriterExt: Sized {
    fn tee<Other>(self, other: Other) -> TeeWriter<Self, Other> {
        TeeWriter {
            this: self,
            other,
            offset: 0,
        }
    }
}

impl<T> TeeWriterExt for T {}

impl<This, Other> TeeWriter<This, Other> {
    /// Consumes the TeeWriter and returns the inner writers and the current offset.
    /// Offset indicates how many more bytes have been written to `this` than `other`.
    /// If offset is positive, `this` has written more bytes.
    /// If offset is negative, `other` has written more bytes.
    /// If offset is zero, both writers are in sync.
    pub fn into_inner(self) -> (This, Other, isize) {
        (self.this, self.other, self.offset)
    }
}
