tachyonfx 0.25.0

A ratatui library for creating shader-like effects in TUIs.
Documentation
//! Duration abstraction for tachyonfx
//! Uses std::time::Duration when std-duration feature is enabled,
//! otherwise uses custom implementation

#[cfg(feature = "std-duration")]
pub type Duration = core::time::Duration;

#[cfg(not(feature = "std-duration"))]
pub type Duration = duration::Duration;

#[cfg(not(feature = "std-duration"))]
#[allow(clippy::module_inception)]
pub mod duration {
    // Your custom Duration implementation goes here

    use core::{
        iter::Sum,
        ops::{Add, AddAssign, Mul, Sub, SubAssign},
    };

    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
    pub struct Duration {
        pub milliseconds: u32,
    }

    impl Duration {
        pub const ZERO: Self = Self { milliseconds: 0 };

        pub const fn from_millis(milliseconds: u32) -> Self {
            Self { milliseconds }
        }

        pub const fn from_secs(seconds: u32) -> Self {
            Self { milliseconds: seconds * 1000 }
        }

        pub fn from_secs_f32(seconds: f32) -> Self {
            Self { milliseconds: (seconds * 1000.0) as u32 }
        }

        pub fn as_millis(self) -> u32 {
            self.milliseconds
        }

        pub const fn is_zero(self) -> bool {
            self.milliseconds == 0
        }

        pub fn as_secs_f32(self) -> f32 {
            self.milliseconds as f32 / 1000.0
        }

        pub fn checked_sub(self, other: Self) -> Option<Self> {
            self.milliseconds
                .checked_sub(other.milliseconds)
                .map(Self::from_millis)
        }
    }

    impl Mul<u32> for Duration {
        type Output = Self;

        fn mul(self, rhs: u32) -> Self {
            Self { milliseconds: self.milliseconds * rhs }
        }
    }

    impl Add<Duration> for Duration {
        type Output = Self;

        fn add(self, rhs: Self) -> Self {
            Self { milliseconds: self.milliseconds + rhs.milliseconds }
        }
    }

    impl Add<u32> for Duration {
        type Output = Self;

        fn add(self, rhs: u32) -> Self {
            Self { milliseconds: self.milliseconds + rhs }
        }
    }

    impl AddAssign<Duration> for Duration {
        fn add_assign(&mut self, rhs: Self) {
            self.milliseconds += rhs.milliseconds;
        }
    }

    impl AddAssign<u32> for Duration {
        fn add_assign(&mut self, rhs: u32) {
            self.milliseconds += rhs;
        }
    }

    impl Sub<Duration> for Duration {
        type Output = Self;

        fn sub(self, rhs: Self) -> Self {
            Self { milliseconds: self.milliseconds - rhs.milliseconds }
        }
    }

    impl Sub<u32> for Duration {
        type Output = Self;

        fn sub(self, rhs: u32) -> Self {
            Self { milliseconds: self.milliseconds - rhs }
        }
    }

    impl SubAssign<Duration> for Duration {
        fn sub_assign(&mut self, rhs: Self) {
            self.milliseconds -= rhs.milliseconds;
        }
    }

    impl SubAssign<u32> for Duration {
        fn sub_assign(&mut self, rhs: u32) {
            self.milliseconds -= rhs;
        }
    }

    impl Mul<Duration> for u32 {
        type Output = Duration;

        fn mul(self, rhs: Duration) -> Self::Output {
            Duration { milliseconds: self * rhs.milliseconds }
        }
    }

    impl Mul<f32> for Duration {
        type Output = Duration;

        fn mul(self, rhs: f32) -> Duration {
            Duration {
                milliseconds: (self.milliseconds as f32 * rhs) as u32,
            }
        }
    }

    impl Sum for Duration {
        fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::ZERO, Add::add)
        }
    }

    #[cfg(all(feature = "std", not(feature = "wasm")))]
    #[allow(clippy::std_instead_of_core)]
    impl From<std::time::Duration> for Duration {
        fn from(d: std::time::Duration) -> Self {
            Self { milliseconds: d.as_millis() as u32 }
        }
    }

    #[cfg(feature = "wasm")]
    impl From<web_time::Duration> for Duration {
        fn from(d: web_time::Duration) -> Self {
            Self { milliseconds: d.as_millis() as u32 }
        }
    }

    #[cfg(all(feature = "std", not(feature = "wasm")))]
    #[allow(clippy::std_instead_of_core)]
    impl From<Duration> for std::time::Duration {
        fn from(d: Duration) -> Self {
            std::time::Duration::from_millis(d.milliseconds as u64)
        }
    }

    #[cfg(feature = "wasm")]
    impl From<Duration> for web_time::Duration {
        fn from(d: Duration) -> Self {
            web_time::Duration::from_millis(d.milliseconds as u64)
        }
    }

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

        #[test]
        fn test_duration_add() {
            let d1 = Duration::from_millis(100);
            let d2 = Duration::from_millis(200);
            assert_eq!(d1 + d2, Duration::from_millis(300));
        }

        #[test]
        fn verify_size_of_duration() {
            assert_eq!(size_of::<Duration>(), 4);
        }

        #[test]
        fn test_duration_sub() {
            let d1 = Duration::from_millis(200);
            let d2 = Duration::from_millis(100);
            assert_eq!(d1 - d2, Duration::from_millis(100));
        }

        #[test]
        fn test_duration_mul() {
            let d1 = Duration::from_millis(100);
            assert_eq!(d1 * 2, Duration::from_millis(200));
        }

        #[test]
        fn test_duration_sum() {
            let durations = [
                Duration::from_millis(100),
                Duration::from_millis(200),
                Duration::from_millis(300),
            ];
            assert_eq!(
                durations.iter().copied().sum::<Duration>(),
                Duration::from_millis(600)
            );
        }

        #[test]
        fn test_duration_from_secs_f32() {
            let d = Duration::from_secs_f32(0.5);
            assert_eq!(d, Duration::from_millis(500));
        }

        #[test]
        fn test_duration_as_secs_f32() {
            let d = Duration::from_millis(500);
            assert_eq!(d.as_secs_f32(), 0.5);
        }

        #[test]
        fn test_duration_checked_sub() {
            let d1 = Duration::from_millis(200);
            let d2 = Duration::from_millis(100);
            assert_eq!(d1.checked_sub(d2), Some(Duration::from_millis(100)));
            assert_eq!(d2.checked_sub(d1), None);
        }
    }
}