//! Provider of [`MapExt`].

use crate::prelude::*;

/// Extention trait for mapping methods.
pub trait MapExt<T> {
    /// Returns mapped value by closure.
    ///
    /// # Examples
    ///
    /// ```
    /// use subject::prelude::*;
    /// use subject::exts::MapExt;
    ///
    /// assert_eq!(S(40).map(|x| x + 2), 42);
    /// ```
    fn map<U, F>(self, f: F) -> U
    where
        Self: Sized,
        F: FnOnce(T) -> U;

    /// Returns mapped value by closure if flag is `true`.
    ///
    /// # Examples
    ///
    /// ```
    /// use subject::prelude::*;
    /// use subject::exts::MapExt;
    ///
    /// assert_eq!(S(40).map_if(false, |x| x + 2), 40);
    /// assert_eq!(S(40).map_if(true, |x| x + 2), 42);
    /// ```
    fn map_if<F>(self, flag: bool, f: F) -> T
    where
        Self: Sized,
        F: FnOnce(T) -> T;
}

impl<T> MapExt<T> for S<T> {
    #[inline]
    fn map<U, F>(self, f: F) -> U
    where
        Self: Sized,
        F: FnOnce(T) -> U,
    {
        f(self.0)
    }

    #[inline]
    fn map_if<F>(self, flag: bool, f: F) -> T
    where
        Self: Sized,
        F: FnOnce(T) -> T,
    {
        if flag { f(self.0) } else { self.0 }
    }
}
