Skip to main content

core/cmp/
clamp.rs

1use crate::marker::Destruct;
2use crate::ops::{RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
3
4/// Trait for ranges supported by [`Ord::clamp_to`].
5#[unstable(feature = "clamp_bounds", issue = "147781")]
6#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
7pub const trait ClampBounds<T>: Sized {
8    /// The implementation of [`Ord::clamp_to`].
9    fn clamp(self, value: T) -> T
10    where
11        T: [const] Destruct;
12}
13
14#[unstable(feature = "clamp_bounds", issue = "147781")]
15#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
16const impl<T> ClampBounds<T> for RangeFrom<T>
17where
18    T: [const] Ord,
19{
20    fn clamp(self, value: T) -> T
21    where
22        T: [const] Destruct,
23    {
24        value.max(self.start)
25    }
26}
27
28#[unstable(feature = "clamp_bounds", issue = "147781")]
29#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
30const impl<T> ClampBounds<T> for RangeToInclusive<T>
31where
32    T: [const] Ord,
33{
34    fn clamp(self, value: T) -> T
35    where
36        T: [const] Destruct,
37    {
38        value.min(self.end)
39    }
40}
41
42#[unstable(feature = "clamp_bounds", issue = "147781")]
43#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
44const impl<T> ClampBounds<T> for RangeInclusive<T>
45where
46    T: [const] Ord,
47{
48    fn clamp(self, value: T) -> T
49    where
50        T: [const] Destruct,
51    {
52        let (start, end) = self.into_inner();
53        value.clamp(start, end)
54    }
55}
56
57#[unstable(feature = "clamp_bounds", issue = "147781")]
58#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
59const impl<T> ClampBounds<T> for RangeFull {
60    fn clamp(self, value: T) -> T {
61        value
62    }
63}
64
65macro impl_for_float($t:ty) {
66    #[unstable(feature = "clamp_bounds", issue = "147781")]
67    #[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
68    const impl ClampBounds<$t> for RangeFrom<$t> {
69        fn clamp(self, value: $t) -> $t {
70            assert!(!self.start.is_nan(), "start was NaN");
71            value.max(self.start)
72        }
73    }
74
75    #[unstable(feature = "clamp_bounds", issue = "147781")]
76    #[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
77    const impl ClampBounds<$t> for RangeToInclusive<$t> {
78        fn clamp(self, value: $t) -> $t {
79            assert!(!self.end.is_nan(), "end was NaN");
80            value.min(self.end)
81        }
82    }
83
84    #[unstable(feature = "clamp_bounds", issue = "147781")]
85    #[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
86    const impl ClampBounds<$t> for RangeInclusive<$t> {
87        #[expect(
88            clippy::neg_cmp_op_on_partial_ord,
89            reason = "NaN check is intentionally included in comparison"
90        )]
91        fn clamp(self, value: $t) -> $t {
92            let (start, end) = self.into_inner();
93            assert!(start <= end, "start > end, or either was NaN");
94            value.clamp(start, end)
95        }
96    }
97}
98
99// #[unstable(feature = "f16", issue = "116909")]
100impl_for_float!(f16);
101impl_for_float!(f32);
102impl_for_float!(f64);
103// #[unstable(feature = "f128", issue = "116909")]
104impl_for_float!(f128);