rat_widget/
range_op.rs

1//!
2//! Bounded numeric operations.
3//!
4
5/// Bounded numeric operations.
6///
7/// Useful for taking steps within a range.
8///
9/// When used with a reversed range it steps
10/// in the reversed direction.
11///
12pub trait RangeOp
13where
14    Self: Sized,
15{
16    type Step;
17
18    /// Addition. Bounded to min/max.
19    fn add_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self;
20
21    /// Subtraction. Bounded to min/max.
22    fn sub_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self;
23}
24
25macro_rules! u_range_op {
26    ($value_ty:ty, $step_ty:ty) => {
27        impl RangeOp for $value_ty {
28            type Step = $step_ty;
29
30            #[inline(always)]
31            fn add_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
32                self.saturating_add(delta).clamp(bounds.0, bounds.1)
33            }
34
35            #[inline(always)]
36            fn sub_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
37                self.saturating_sub(delta).clamp(bounds.0, bounds.1)
38            }
39        }
40    };
41}
42
43macro_rules! i_range_op {
44    ($value_ty:ty, $step_ty:ty) => {
45        impl RangeOp for $value_ty {
46            type Step = $step_ty;
47
48            #[inline(always)]
49            fn add_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
50                self.saturating_add_unsigned(delta)
51                    .clamp(bounds.0, bounds.1)
52            }
53
54            #[inline(always)]
55            fn sub_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
56                self.saturating_sub_unsigned(delta)
57                    .clamp(bounds.0, bounds.1)
58            }
59        }
60    };
61}
62
63u_range_op!(u8, u8);
64u_range_op!(u16, u16);
65u_range_op!(u32, u32);
66u_range_op!(u64, u64);
67u_range_op!(u128, u128);
68u_range_op!(usize, usize);
69i_range_op!(i8, u8);
70i_range_op!(i16, u16);
71i_range_op!(i32, u32);
72i_range_op!(i64, u64);
73i_range_op!(i128, u128);
74i_range_op!(isize, usize);
75
76impl RangeOp for f32 {
77    type Step = f32;
78
79    #[inline(always)]
80    fn add_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
81        (self + delta).clamp(bounds.0, bounds.1)
82    }
83
84    #[inline(always)]
85    fn sub_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
86        (self - delta).clamp(bounds.0, bounds.1)
87    }
88}
89
90impl RangeOp for f64 {
91    type Step = f64;
92
93    #[inline(always)]
94    fn add_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
95        (self + delta).clamp(bounds.0, bounds.1)
96    }
97
98    #[inline(always)]
99    fn sub_clamp(self, delta: Self::Step, bounds: (Self, Self)) -> Self {
100        (self - delta).clamp(bounds.0, bounds.1)
101    }
102}