//! Call on any value, passing a closure, which takes that value returning
//! T, which is returned from this function
//! # Example:
//! ```
//! use tsaw::TSaw;
//! let result: Vec<String> = " Foo\nbaR"
//!     .split_whitespace()
//!     .filter_map(|str|
//!         str.trim()
//!            .to_lowercase()
//!            .tsaw(|str| (!str.is_empty()).then_some(str))
//!      )
//!      .collect();
//!
//! let other_result: Vec<String> = " Foo\nbaR"
//!     .split_whitespace()
//!     .filter_map(|str| {
//!         let str = str.trim().to_lowercase();
//!         (!str.is_empty()).then_some(str)
//!     })
//!     .collect();
//!
//! assert_eq!(result, ["foo", "bar"]);
//! assert_eq!(result, other_result);
//! ```

pub trait TSaw {
    /// Call on any value, passing a closure, which takes that value returning
    /// T, which is returned from this function
    /// # Example:
    /// ```
    /// use tsaw::TSaw;
    /// let result: Vec<String> = " Foo\nbaR"
    ///     .split_whitespace()
    ///     .filter_map(|str|
    ///         str.trim()
    ///            .to_lowercase()
    ///            .tsaw(|str| (!str.is_empty()).then_some(str))
    ///      )
    ///      .collect();
    ///
    /// let other_result: Vec<String> = " Foo\nbaR"
    ///     .split_whitespace()
    ///     .filter_map(|str| {
    ///         let str = str.trim().to_lowercase();
    ///         (!str.is_empty()).then_some(str)
    ///     })
    ///     .collect();
    ///
    /// assert_eq!(result, ["foo", "bar"]);
    /// assert_eq!(result, other_result);
    /// ```
    fn tsaw<T>(self, f: impl FnOnce(Self) -> T) -> T
    where
        Self: Sized,
    {
        f(self)
    }
}

impl<T> TSaw for T {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn mutates_str() {
        let result: Vec<String> = " Foo\nbaR"
            .split_whitespace()
            .filter_map(|str| {
                str.trim()
                    .to_lowercase()
                    .tsaw(|str| (!str.is_empty()).then_some(str))
            })
            .collect();

        let other_result: Vec<String> = " Foo\nbaR"
            .split_whitespace()
            .filter_map(|str| {
                let str = str.trim().to_lowercase();

                (!str.is_empty()).then_some(str)
            })
            .collect();

        assert_eq!(result, ["foo", "bar"]);
        assert_eq!(result, other_result);
    }
}
