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 Some(unsafe { $name(crate::mem::transmute(val)) })
28 } else {
29 None
30 }
31 }
32
33 #[inline]
40 pub const unsafe fn new_unchecked(val: $int) -> Self {
41 unsafe { crate::mem::transmute(val) }
43 }
44
45 #[inline]
46 pub const fn as_inner(self) -> $int {
47 unsafe { crate::mem::transmute(self) }
50 }
51 }
52
53 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 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
96define_valid_range_type! {
97 pub struct Nanoseconds(u32 is 0..=999_999_999);
98}
99
100impl Nanoseconds {
101 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
115define_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
158define_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}