Skip to main content

core/num/
niche_types.rs

1#![unstable(
2    feature = "temporary_niche_types",
3    issue = "none",
4    reason = "for core, alloc, and std internals until pattern types are further along"
5)]
6
7use crate::cmp::Ordering;
8use crate::hash::{Hash, Hasher};
9use crate::marker::StructuralPartialEq;
10use crate::{fmt, pattern_type};
11
12macro_rules! define_valid_range_type {
13    ($(
14        $(#[$m:meta])*
15        $vis:vis struct $name:ident($int:ident is $pat:pat);
16    )+) => {$(
17        #[derive(Clone, Copy)]
18        #[repr(transparent)]
19        $(#[$m])*
20        $vis struct $name(pattern_type!($int is $pat));
21        impl $name {
22            #[inline]
23            pub const fn new(val: $int) -> Option<Self> {
24                #[allow(non_contiguous_range_endpoints)]
25                if let $pat = val {
26                    // SAFETY: just checked that the value matches the pattern
27                    Some(unsafe { $name(crate::mem::transmute(val)) })
28                } else {
29                    None
30                }
31            }
32
33            /// Constructs an instance of this type from the underlying integer
34            /// primitive without checking whether its valid.
35            ///
36            /// # Safety
37            /// Immediate language UB if `val` is not within the valid range for this
38            /// type, as it violates the validity invariant.
39            #[inline]
40            pub const unsafe fn new_unchecked(val: $int) -> Self {
41                // SAFETY: Caller promised that `val` is within the valid range.
42                unsafe { crate::mem::transmute(val) }
43            }
44
45            #[inline]
46            pub const fn as_inner(self) -> $int {
47                // SAFETY: pattern types are always legal values of their base type
48                // (Not using `.0` because that has perf regressions.)
49                unsafe { crate::mem::transmute(self) }
50            }
51        }
52
53        // This is required to allow matching a constant.  We don't get it from a derive
54        // because the derived `PartialEq` would do a field projection, which is banned
55        // by <https://github.com/rust-lang/compiler-team/issues/807>.
56        impl StructuralPartialEq for $name {}
57
58        impl Eq for $name {}
59
60        impl PartialEq for $name {
61            #[inline]
62            fn eq(&self, other: &Self) -> bool {
63                self.as_inner() == other.as_inner()
64            }
65        }
66
67        impl Ord for $name {
68            #[inline]
69            fn cmp(&self, other: &Self) -> Ordering {
70                Ord::cmp(&self.as_inner(), &other.as_inner())
71            }
72        }
73
74        impl PartialOrd for $name {
75            #[inline]
76            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77                Some(Ord::cmp(self, other))
78            }
79        }
80
81        impl Hash for $name {
82            // Required method
83            fn hash<H: Hasher>(&self, state: &mut H) {
84                Hash::hash(&self.as_inner(), state);
85            }
86        }
87
88        impl fmt::Debug for $name {
89            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90                <$int as fmt::Debug>::fmt(&self.as_inner(), f)
91            }
92        }
93    )+};
94}
95
96#[automatically_derived]
impl crate::clone::Clone for Nanoseconds {
    #[inline]
    fn clone(&self) -> Nanoseconds {
        let _:
                crate::clone::AssertParamIsClone<u32 is const 0..=const 999_999_999>;
        *self
    }
}
#[automatically_derived]
impl crate::marker::Copy for Nanoseconds { }
impl Nanoseconds {
    #[inline]
    pub const fn new(val: u32) -> Option<Self> {

        #[allow(non_contiguous_range_endpoints)]
        if let 0..=999_999_999 = val {
            Some(unsafe { Nanoseconds(crate::mem::transmute(val)) })
        } else { None }
    }
    /// Constructs an instance of this type from the underlying integer
    /// primitive without checking whether its valid.
    ///
    /// # Safety
    /// Immediate language UB if `val` is not within the valid range for this
    /// type, as it violates the validity invariant.
    #[inline]
    pub const unsafe fn new_unchecked(val: u32) -> Self {
        unsafe { crate::mem::transmute(val) }
    }
    #[inline]
    pub const fn as_inner(self) -> u32 {
        unsafe { crate::mem::transmute(self) }
    }
}
impl StructuralPartialEq for Nanoseconds {}
impl Eq for Nanoseconds {}
impl PartialEq for Nanoseconds {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.as_inner() == other.as_inner() }
}
impl Ord for Nanoseconds {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        Ord::cmp(&self.as_inner(), &other.as_inner())
    }
}
impl PartialOrd for Nanoseconds {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(Ord::cmp(self, other))
    }
}
impl Hash for Nanoseconds {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.as_inner(), state);
    }
}
impl fmt::Debug for Nanoseconds {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <u32 as fmt::Debug>::fmt(&self.as_inner(), f)
    }
}define_valid_range_type! {
97    pub struct Nanoseconds(u32 is 0..=999_999_999);
98}
99
100impl Nanoseconds {
101    // SAFETY: 0 is within the valid range
102    pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) };
103}
104
105#[rustc_const_unstable(feature = "const_default", issue = "143894")]
106impl const Default for Nanoseconds {
107    #[inline]
108    fn default() -> Self {
109        Self::ZERO
110    }
111}
112
113const HALF_USIZE: usize = usize::MAX >> 1;
114
115#[automatically_derived]
impl crate::clone::Clone for NonZeroCharInner {
    #[inline]
    fn clone(&self) -> NonZeroCharInner {
        let _:
                crate::clone::AssertParamIsClone<char is const '\u{1}'..=const '\u{10ffff}'>;
        *self
    }
}
#[automatically_derived]
impl crate::marker::Copy for NonZeroCharInner { }
impl NonZeroCharInner {
    #[inline]
    pub const fn new(val: char) -> Option<Self> {

        #[allow(non_contiguous_range_endpoints)]
        if let '\u{1}'..='\u{10ffff}' = val {
            Some(unsafe { NonZeroCharInner(crate::mem::transmute(val)) })
        } else { None }
    }
    /// Constructs an instance of this type from the underlying integer
    /// primitive without checking whether its valid.
    ///
    /// # Safety
    /// Immediate language UB if `val` is not within the valid range for this
    /// type, as it violates the validity invariant.
    #[inline]
    pub const unsafe fn new_unchecked(val: char) -> Self {
        unsafe { crate::mem::transmute(val) }
    }
    #[inline]
    pub const fn as_inner(self) -> char {
        unsafe { crate::mem::transmute(self) }
    }
}
impl StructuralPartialEq for NonZeroCharInner {}
impl Eq for NonZeroCharInner {}
impl PartialEq for NonZeroCharInner {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.as_inner() == other.as_inner() }
}
impl Ord for NonZeroCharInner {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        Ord::cmp(&self.as_inner(), &other.as_inner())
    }
}
impl PartialOrd for NonZeroCharInner {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(Ord::cmp(self, other))
    }
}
impl Hash for NonZeroCharInner {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.as_inner(), state);
    }
}
impl fmt::Debug for NonZeroCharInner {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <char as fmt::Debug>::fmt(&self.as_inner(), f)
    }
}define_valid_range_type! {
116    pub struct NonZeroU8Inner(u8 is 1..);
117    pub struct NonZeroU16Inner(u16 is 1..);
118    pub struct NonZeroU32Inner(u32 is 1..);
119    pub struct NonZeroU64Inner(u64 is 1..);
120    pub struct NonZeroU128Inner(u128 is 1..);
121
122    pub struct NonZeroI8Inner(i8 is ..0 | 1..);
123    pub struct NonZeroI16Inner(i16 is ..0 | 1..);
124    pub struct NonZeroI32Inner(i32 is ..0 | 1..);
125    pub struct NonZeroI64Inner(i64 is ..0 | 1..);
126    pub struct NonZeroI128Inner(i128 is ..0 | 1..);
127
128    pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE);
129    pub struct NonZeroUsizeInner(usize is 1..);
130    pub struct NonZeroIsizeInner(isize is ..0 | 1..);
131
132    pub struct U32NotAllOnes(u32 is 0..u32::MAX);
133    pub struct I32NotAllOnes(i32 is ..-1 | 0..);
134
135    pub struct U64NotAllOnes(u64 is 0..u64::MAX);
136    pub struct I64NotAllOnes(i64 is ..-1 | 0..);
137
138    pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}');
139}
140
141pub trait NotAllOnesHelper {
142    type Type;
143}
144pub type NotAllOnes<T> = <T as NotAllOnesHelper>::Type;
145impl NotAllOnesHelper for u32 {
146    type Type = U32NotAllOnes;
147}
148impl NotAllOnesHelper for i32 {
149    type Type = I32NotAllOnes;
150}
151impl NotAllOnesHelper for u64 {
152    type Type = U64NotAllOnes;
153}
154impl NotAllOnesHelper for i64 {
155    type Type = I64NotAllOnes;
156}
157
158#[automatically_derived]
impl crate::clone::Clone for CodePointInner {
    #[inline]
    fn clone(&self) -> CodePointInner {
        let _:
                crate::clone::AssertParamIsClone<u32 is const 0..=const 0x10ffff>;
        *self
    }
}
#[automatically_derived]
impl crate::marker::Copy for CodePointInner { }
impl CodePointInner {
    #[inline]
    pub const fn new(val: u32) -> Option<Self> {

        #[allow(non_contiguous_range_endpoints)]
        if let 0..=0x10ffff = val {
            Some(unsafe { CodePointInner(crate::mem::transmute(val)) })
        } else { None }
    }
    /// Constructs an instance of this type from the underlying integer
    /// primitive without checking whether its valid.
    ///
    /// # Safety
    /// Immediate language UB if `val` is not within the valid range for this
    /// type, as it violates the validity invariant.
    #[inline]
    pub const unsafe fn new_unchecked(val: u32) -> Self {
        unsafe { crate::mem::transmute(val) }
    }
    #[inline]
    pub const fn as_inner(self) -> u32 {
        unsafe { crate::mem::transmute(self) }
    }
}
impl StructuralPartialEq for CodePointInner {}
impl Eq for CodePointInner {}
impl PartialEq for CodePointInner {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.as_inner() == other.as_inner() }
}
impl Ord for CodePointInner {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        Ord::cmp(&self.as_inner(), &other.as_inner())
    }
}
impl PartialOrd for CodePointInner {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(Ord::cmp(self, other))
    }
}
impl Hash for CodePointInner {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.as_inner(), state);
    }
}
impl fmt::Debug for CodePointInner {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <u32 as fmt::Debug>::fmt(&self.as_inner(), f)
    }
}define_valid_range_type! {
159    pub struct CodePointInner(u32 is 0..=0x10ffff);
160}
161
162impl CodePointInner {
163    pub const ZERO: Self = CodePointInner::new(0).unwrap();
164}
165
166impl Default for CodePointInner {
167    #[inline]
168    fn default() -> Self {
169        Self::ZERO
170    }
171}