1 | use super::TryFrom; |
2 | use crate::num::TryFromIntError; |
3 | |
4 | mod private { |
5 | /// This trait being unreachable from outside the crate |
6 | /// prevents other implementations of the `FloatToInt` trait, |
7 | /// which allows potentially adding more trait methods after the trait is `#[stable]`. |
8 | #[unstable (feature = "convert_float_to_int" , issue = "67057" )] |
9 | pub trait Sealed {} |
10 | } |
11 | |
12 | /// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`. |
13 | /// Typically doesn’t need to be used directly. |
14 | #[unstable (feature = "convert_float_to_int" , issue = "67057" )] |
15 | pub trait FloatToInt<Int>: private::Sealed + Sized { |
16 | #[unstable (feature = "convert_float_to_int" , issue = "67057" )] |
17 | #[doc (hidden)] |
18 | unsafe fn to_int_unchecked(self) -> Int; |
19 | } |
20 | |
21 | macro_rules! impl_float_to_int { |
22 | ( $Float: ident => $( $Int: ident )+ ) => { |
23 | #[unstable(feature = "convert_float_to_int" , issue = "67057" )] |
24 | impl private::Sealed for $Float {} |
25 | $( |
26 | #[unstable(feature = "convert_float_to_int" , issue = "67057" )] |
27 | impl FloatToInt<$Int> for $Float { |
28 | #[inline] |
29 | unsafe fn to_int_unchecked(self) -> $Int { |
30 | // SAFETY: the safety contract must be upheld by the caller. |
31 | unsafe { crate::intrinsics::float_to_int_unchecked(self) } |
32 | } |
33 | } |
34 | )+ |
35 | } |
36 | } |
37 | |
38 | impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); |
39 | impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); |
40 | |
41 | // Conversion traits for primitive integer and float types |
42 | // Conversions T -> T are covered by a blanket impl and therefore excluded |
43 | // Some conversions from and to usize/isize are not implemented due to portability concerns |
44 | macro_rules! impl_from { |
45 | ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { |
46 | #[$attr] |
47 | impl From<$Small> for $Large { |
48 | // Rustdocs on the impl block show a "[+] show undocumented items" toggle. |
49 | // Rustdocs on functions do not. |
50 | #[doc = $doc] |
51 | #[inline(always)] |
52 | fn from(small: $Small) -> Self { |
53 | small as Self |
54 | } |
55 | } |
56 | }; |
57 | ($Small: ty, $Large: ty, #[$attr:meta]) => { |
58 | impl_from!($Small, |
59 | $Large, |
60 | #[$attr], |
61 | concat!("Converts `" , |
62 | stringify!($Small), |
63 | "` to `" , |
64 | stringify!($Large), |
65 | "` losslessly." )); |
66 | } |
67 | } |
68 | |
69 | macro_rules! impl_from_bool { |
70 | ($target: ty, #[$attr:meta]) => { |
71 | impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `" , |
72 | stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true` |
73 | values. |
74 | |
75 | # Examples |
76 | |
77 | ``` |
78 | assert_eq!(" , stringify!($target), "::from(true), 1); |
79 | assert_eq!(" , stringify!($target), "::from(false), 0); |
80 | ```" )); |
81 | }; |
82 | } |
83 | |
84 | // Bool -> Any |
85 | impl_from_bool! { u8, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
86 | impl_from_bool! { u16, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
87 | impl_from_bool! { u32, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
88 | impl_from_bool! { u64, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
89 | impl_from_bool! { u128, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
90 | impl_from_bool! { usize, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
91 | impl_from_bool! { i8, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
92 | impl_from_bool! { i16, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
93 | impl_from_bool! { i32, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
94 | impl_from_bool! { i64, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
95 | impl_from_bool! { i128, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
96 | impl_from_bool! { isize, #[stable (feature = "from_bool" , since = "1.28.0" )] } |
97 | |
98 | // Unsigned -> Unsigned |
99 | impl_from! { u8, u16, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
100 | impl_from! { u8, u32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
101 | impl_from! { u8, u64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
102 | impl_from! { u8, u128, #[stable (feature = "i128" , since = "1.26.0" )] } |
103 | impl_from! { u8, usize, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
104 | impl_from! { u16, u32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
105 | impl_from! { u16, u64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
106 | impl_from! { u16, u128, #[stable (feature = "i128" , since = "1.26.0" )] } |
107 | impl_from! { u32, u64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
108 | impl_from! { u32, u128, #[stable (feature = "i128" , since = "1.26.0" )] } |
109 | impl_from! { u64, u128, #[stable (feature = "i128" , since = "1.26.0" )] } |
110 | |
111 | // Signed -> Signed |
112 | impl_from! { i8, i16, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
113 | impl_from! { i8, i32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
114 | impl_from! { i8, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
115 | impl_from! { i8, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
116 | impl_from! { i8, isize, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
117 | impl_from! { i16, i32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
118 | impl_from! { i16, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
119 | impl_from! { i16, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
120 | impl_from! { i32, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
121 | impl_from! { i32, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
122 | impl_from! { i64, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
123 | |
124 | // Unsigned -> Signed |
125 | impl_from! { u8, i16, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
126 | impl_from! { u8, i32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
127 | impl_from! { u8, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
128 | impl_from! { u8, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
129 | impl_from! { u16, i32, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
130 | impl_from! { u16, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
131 | impl_from! { u16, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
132 | impl_from! { u32, i64, #[stable (feature = "lossless_int_conv" , since = "1.5.0" )] } |
133 | impl_from! { u32, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
134 | impl_from! { u64, i128, #[stable (feature = "i128" , since = "1.26.0" )] } |
135 | |
136 | // The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX |
137 | // which imply that pointer-sized integers must be at least 16 bits: |
138 | // https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 |
139 | impl_from! { u16, usize, #[stable (feature = "lossless_iusize_conv" , since = "1.26.0" )] } |
140 | impl_from! { u8, isize, #[stable (feature = "lossless_iusize_conv" , since = "1.26.0" )] } |
141 | impl_from! { i16, isize, #[stable (feature = "lossless_iusize_conv" , since = "1.26.0" )] } |
142 | |
143 | // RISC-V defines the possibility of a 128-bit address space (RV128). |
144 | |
145 | // CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize. |
146 | // https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf |
147 | // https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf |
148 | |
149 | // Note: integers can only be represented with full precision in a float if |
150 | // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. |
151 | // Lossy float conversions are not implemented at this time. |
152 | |
153 | // Signed -> Float |
154 | impl_from! { i8, f32, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
155 | impl_from! { i8, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
156 | impl_from! { i16, f32, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
157 | impl_from! { i16, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
158 | impl_from! { i32, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
159 | |
160 | // Unsigned -> Float |
161 | impl_from! { u8, f32, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
162 | impl_from! { u8, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
163 | impl_from! { u16, f32, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
164 | impl_from! { u16, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
165 | impl_from! { u32, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
166 | |
167 | // Float -> Float |
168 | impl_from! { f32, f64, #[stable (feature = "lossless_float_conv" , since = "1.6.0" )] } |
169 | |
170 | // bool -> Float |
171 | #[stable (feature = "float_from_bool" , since = "1.68.0" )] |
172 | impl From<bool> for f32 { |
173 | /// Converts `bool` to `f32` losslessly. The resulting value is positive |
174 | /// `0.0` for `false` and `1.0` for `true` values. |
175 | /// |
176 | /// # Examples |
177 | /// ``` |
178 | /// let x: f32 = false.into(); |
179 | /// assert_eq!(x, 0.0); |
180 | /// assert!(x.is_sign_positive()); |
181 | /// |
182 | /// let y: f32 = true.into(); |
183 | /// assert_eq!(y, 1.0); |
184 | /// ``` |
185 | #[inline ] |
186 | fn from(small: bool) -> Self { |
187 | small as u8 as Self |
188 | } |
189 | } |
190 | #[stable (feature = "float_from_bool" , since = "1.68.0" )] |
191 | impl From<bool> for f64 { |
192 | /// Converts `bool` to `f64` losslessly. The resulting value is positive |
193 | /// `0.0` for `false` and `1.0` for `true` values. |
194 | /// |
195 | /// # Examples |
196 | /// ``` |
197 | /// let x: f64 = false.into(); |
198 | /// assert_eq!(x, 0.0); |
199 | /// assert!(x.is_sign_positive()); |
200 | /// |
201 | /// let y: f64 = true.into(); |
202 | /// assert_eq!(y, 1.0); |
203 | /// ``` |
204 | #[inline ] |
205 | fn from(small: bool) -> Self { |
206 | small as u8 as Self |
207 | } |
208 | } |
209 | |
210 | // no possible bounds violation |
211 | macro_rules! try_from_unbounded { |
212 | ($source:ty, $($target:ty),*) => {$( |
213 | #[stable(feature = "try_from" , since = "1.34.0" )] |
214 | impl TryFrom<$source> for $target { |
215 | type Error = TryFromIntError; |
216 | |
217 | /// Try to create the target number type from a source |
218 | /// number type. This returns an error if the source value |
219 | /// is outside of the range of the target type. |
220 | #[inline] |
221 | fn try_from(value: $source) -> Result<Self, Self::Error> { |
222 | Ok(value as Self) |
223 | } |
224 | } |
225 | )*} |
226 | } |
227 | |
228 | // only negative bounds |
229 | macro_rules! try_from_lower_bounded { |
230 | ($source:ty, $($target:ty),*) => {$( |
231 | #[stable(feature = "try_from" , since = "1.34.0" )] |
232 | impl TryFrom<$source> for $target { |
233 | type Error = TryFromIntError; |
234 | |
235 | /// Try to create the target number type from a source |
236 | /// number type. This returns an error if the source value |
237 | /// is outside of the range of the target type. |
238 | #[inline] |
239 | fn try_from(u: $source) -> Result<Self, Self::Error> { |
240 | if u >= 0 { |
241 | Ok(u as Self) |
242 | } else { |
243 | Err(TryFromIntError(())) |
244 | } |
245 | } |
246 | } |
247 | )*} |
248 | } |
249 | |
250 | // unsigned to signed (only positive bound) |
251 | macro_rules! try_from_upper_bounded { |
252 | ($source:ty, $($target:ty),*) => {$( |
253 | #[stable(feature = "try_from" , since = "1.34.0" )] |
254 | impl TryFrom<$source> for $target { |
255 | type Error = TryFromIntError; |
256 | |
257 | /// Try to create the target number type from a source |
258 | /// number type. This returns an error if the source value |
259 | /// is outside of the range of the target type. |
260 | #[inline] |
261 | fn try_from(u: $source) -> Result<Self, Self::Error> { |
262 | if u > (Self::MAX as $source) { |
263 | Err(TryFromIntError(())) |
264 | } else { |
265 | Ok(u as Self) |
266 | } |
267 | } |
268 | } |
269 | )*} |
270 | } |
271 | |
272 | // all other cases |
273 | macro_rules! try_from_both_bounded { |
274 | ($source:ty, $($target:ty),*) => {$( |
275 | #[stable(feature = "try_from" , since = "1.34.0" )] |
276 | impl TryFrom<$source> for $target { |
277 | type Error = TryFromIntError; |
278 | |
279 | /// Try to create the target number type from a source |
280 | /// number type. This returns an error if the source value |
281 | /// is outside of the range of the target type. |
282 | #[inline] |
283 | fn try_from(u: $source) -> Result<Self, Self::Error> { |
284 | let min = Self::MIN as $source; |
285 | let max = Self::MAX as $source; |
286 | if u < min || u > max { |
287 | Err(TryFromIntError(())) |
288 | } else { |
289 | Ok(u as Self) |
290 | } |
291 | } |
292 | } |
293 | )*} |
294 | } |
295 | |
296 | macro_rules! rev { |
297 | ($mac:ident, $source:ty, $($target:ty),*) => {$( |
298 | $mac!($target, $source); |
299 | )*} |
300 | } |
301 | |
302 | // intra-sign conversions |
303 | try_from_upper_bounded!(u16, u8); |
304 | try_from_upper_bounded!(u32, u16, u8); |
305 | try_from_upper_bounded!(u64, u32, u16, u8); |
306 | try_from_upper_bounded!(u128, u64, u32, u16, u8); |
307 | |
308 | try_from_both_bounded!(i16, i8); |
309 | try_from_both_bounded!(i32, i16, i8); |
310 | try_from_both_bounded!(i64, i32, i16, i8); |
311 | try_from_both_bounded!(i128, i64, i32, i16, i8); |
312 | |
313 | // unsigned-to-signed |
314 | try_from_upper_bounded!(u8, i8); |
315 | try_from_upper_bounded!(u16, i8, i16); |
316 | try_from_upper_bounded!(u32, i8, i16, i32); |
317 | try_from_upper_bounded!(u64, i8, i16, i32, i64); |
318 | try_from_upper_bounded!(u128, i8, i16, i32, i64, i128); |
319 | |
320 | // signed-to-unsigned |
321 | try_from_lower_bounded!(i8, u8, u16, u32, u64, u128); |
322 | try_from_lower_bounded!(i16, u16, u32, u64, u128); |
323 | try_from_lower_bounded!(i32, u32, u64, u128); |
324 | try_from_lower_bounded!(i64, u64, u128); |
325 | try_from_lower_bounded!(i128, u128); |
326 | try_from_both_bounded!(i16, u8); |
327 | try_from_both_bounded!(i32, u16, u8); |
328 | try_from_both_bounded!(i64, u32, u16, u8); |
329 | try_from_both_bounded!(i128, u64, u32, u16, u8); |
330 | |
331 | // usize/isize |
332 | try_from_upper_bounded!(usize, isize); |
333 | try_from_lower_bounded!(isize, usize); |
334 | |
335 | #[cfg (target_pointer_width = "16" )] |
336 | mod ptr_try_from_impls { |
337 | use super::TryFromIntError; |
338 | use crate::convert::TryFrom; |
339 | |
340 | try_from_upper_bounded!(usize, u8); |
341 | try_from_unbounded!(usize, u16, u32, u64, u128); |
342 | try_from_upper_bounded!(usize, i8, i16); |
343 | try_from_unbounded!(usize, i32, i64, i128); |
344 | |
345 | try_from_both_bounded!(isize, u8); |
346 | try_from_lower_bounded!(isize, u16, u32, u64, u128); |
347 | try_from_both_bounded!(isize, i8); |
348 | try_from_unbounded!(isize, i16, i32, i64, i128); |
349 | |
350 | rev!(try_from_upper_bounded, usize, u32, u64, u128); |
351 | rev!(try_from_lower_bounded, usize, i8, i16); |
352 | rev!(try_from_both_bounded, usize, i32, i64, i128); |
353 | |
354 | rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); |
355 | rev!(try_from_both_bounded, isize, i32, i64, i128); |
356 | } |
357 | |
358 | #[cfg (target_pointer_width = "32" )] |
359 | mod ptr_try_from_impls { |
360 | use super::TryFromIntError; |
361 | use crate::convert::TryFrom; |
362 | |
363 | try_from_upper_bounded!(usize, u8, u16); |
364 | try_from_unbounded!(usize, u32, u64, u128); |
365 | try_from_upper_bounded!(usize, i8, i16, i32); |
366 | try_from_unbounded!(usize, i64, i128); |
367 | |
368 | try_from_both_bounded!(isize, u8, u16); |
369 | try_from_lower_bounded!(isize, u32, u64, u128); |
370 | try_from_both_bounded!(isize, i8, i16); |
371 | try_from_unbounded!(isize, i32, i64, i128); |
372 | |
373 | rev!(try_from_unbounded, usize, u32); |
374 | rev!(try_from_upper_bounded, usize, u64, u128); |
375 | rev!(try_from_lower_bounded, usize, i8, i16, i32); |
376 | rev!(try_from_both_bounded, usize, i64, i128); |
377 | |
378 | rev!(try_from_unbounded, isize, u16); |
379 | rev!(try_from_upper_bounded, isize, u32, u64, u128); |
380 | rev!(try_from_unbounded, isize, i32); |
381 | rev!(try_from_both_bounded, isize, i64, i128); |
382 | } |
383 | |
384 | #[cfg (target_pointer_width = "64" )] |
385 | mod ptr_try_from_impls { |
386 | use super::TryFromIntError; |
387 | use crate::convert::TryFrom; |
388 | |
389 | try_from_upper_bounded!(usize, u8, u16, u32); |
390 | try_from_unbounded!(usize, u64, u128); |
391 | try_from_upper_bounded!(usize, i8, i16, i32, i64); |
392 | try_from_unbounded!(usize, i128); |
393 | |
394 | try_from_both_bounded!(isize, u8, u16, u32); |
395 | try_from_lower_bounded!(isize, u64, u128); |
396 | try_from_both_bounded!(isize, i8, i16, i32); |
397 | try_from_unbounded!(isize, i64, i128); |
398 | |
399 | rev!(try_from_unbounded, usize, u32, u64); |
400 | rev!(try_from_upper_bounded, usize, u128); |
401 | rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); |
402 | rev!(try_from_both_bounded, usize, i128); |
403 | |
404 | rev!(try_from_unbounded, isize, u16, u32); |
405 | rev!(try_from_upper_bounded, isize, u64, u128); |
406 | rev!(try_from_unbounded, isize, i32, i64); |
407 | rev!(try_from_both_bounded, isize, i128); |
408 | } |
409 | |
410 | // Conversion traits for non-zero integer types |
411 | use crate::num::NonZeroI128; |
412 | use crate::num::NonZeroI16; |
413 | use crate::num::NonZeroI32; |
414 | use crate::num::NonZeroI64; |
415 | use crate::num::NonZeroI8; |
416 | use crate::num::NonZeroIsize; |
417 | use crate::num::NonZeroU128; |
418 | use crate::num::NonZeroU16; |
419 | use crate::num::NonZeroU32; |
420 | use crate::num::NonZeroU64; |
421 | use crate::num::NonZeroU8; |
422 | use crate::num::NonZeroUsize; |
423 | |
424 | macro_rules! nzint_impl_from { |
425 | ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { |
426 | #[$attr] |
427 | impl From<$Small> for $Large { |
428 | // Rustdocs on the impl block show a "[+] show undocumented items" toggle. |
429 | // Rustdocs on functions do not. |
430 | #[doc = $doc] |
431 | #[inline] |
432 | fn from(small: $Small) -> Self { |
433 | // SAFETY: input type guarantees the value is non-zero |
434 | unsafe { |
435 | Self::new_unchecked(From::from(small.get())) |
436 | } |
437 | } |
438 | } |
439 | }; |
440 | ($Small: ty, $Large: ty, #[$attr:meta]) => { |
441 | nzint_impl_from!($Small, |
442 | $Large, |
443 | #[$attr], |
444 | concat!("Converts `" , |
445 | stringify!($Small), |
446 | "` to `" , |
447 | stringify!($Large), |
448 | "` losslessly." )); |
449 | } |
450 | } |
451 | |
452 | // Non-zero Unsigned -> Non-zero Unsigned |
453 | nzint_impl_from! { NonZeroU8, NonZeroU16, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
454 | nzint_impl_from! { NonZeroU8, NonZeroU32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
455 | nzint_impl_from! { NonZeroU8, NonZeroU64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
456 | nzint_impl_from! { NonZeroU8, NonZeroU128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
457 | nzint_impl_from! { NonZeroU8, NonZeroUsize, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
458 | nzint_impl_from! { NonZeroU16, NonZeroU32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
459 | nzint_impl_from! { NonZeroU16, NonZeroU64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
460 | nzint_impl_from! { NonZeroU16, NonZeroU128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
461 | nzint_impl_from! { NonZeroU16, NonZeroUsize, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
462 | nzint_impl_from! { NonZeroU32, NonZeroU64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
463 | nzint_impl_from! { NonZeroU32, NonZeroU128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
464 | nzint_impl_from! { NonZeroU64, NonZeroU128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
465 | |
466 | // Non-zero Signed -> Non-zero Signed |
467 | nzint_impl_from! { NonZeroI8, NonZeroI16, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
468 | nzint_impl_from! { NonZeroI8, NonZeroI32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
469 | nzint_impl_from! { NonZeroI8, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
470 | nzint_impl_from! { NonZeroI8, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
471 | nzint_impl_from! { NonZeroI8, NonZeroIsize, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
472 | nzint_impl_from! { NonZeroI16, NonZeroI32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
473 | nzint_impl_from! { NonZeroI16, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
474 | nzint_impl_from! { NonZeroI16, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
475 | nzint_impl_from! { NonZeroI16, NonZeroIsize, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
476 | nzint_impl_from! { NonZeroI32, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
477 | nzint_impl_from! { NonZeroI32, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
478 | nzint_impl_from! { NonZeroI64, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
479 | |
480 | // NonZero UnSigned -> Non-zero Signed |
481 | nzint_impl_from! { NonZeroU8, NonZeroI16, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
482 | nzint_impl_from! { NonZeroU8, NonZeroI32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
483 | nzint_impl_from! { NonZeroU8, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
484 | nzint_impl_from! { NonZeroU8, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
485 | nzint_impl_from! { NonZeroU8, NonZeroIsize, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
486 | nzint_impl_from! { NonZeroU16, NonZeroI32, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
487 | nzint_impl_from! { NonZeroU16, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
488 | nzint_impl_from! { NonZeroU16, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
489 | nzint_impl_from! { NonZeroU32, NonZeroI64, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
490 | nzint_impl_from! { NonZeroU32, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
491 | nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable (feature = "nz_int_conv" , since = "1.41.0" )] } |
492 | |
493 | macro_rules! nzint_impl_try_from_int { |
494 | ($Int: ty, $NonZeroInt: ty, #[$attr:meta], $doc: expr) => { |
495 | #[$attr] |
496 | impl TryFrom<$Int> for $NonZeroInt { |
497 | type Error = TryFromIntError; |
498 | |
499 | // Rustdocs on the impl block show a "[+] show undocumented items" toggle. |
500 | // Rustdocs on functions do not. |
501 | #[doc = $doc] |
502 | #[inline] |
503 | fn try_from(value: $Int) -> Result<Self, Self::Error> { |
504 | Self::new(value).ok_or(TryFromIntError(())) |
505 | } |
506 | } |
507 | }; |
508 | ($Int: ty, $NonZeroInt: ty, #[$attr:meta]) => { |
509 | nzint_impl_try_from_int!($Int, |
510 | $NonZeroInt, |
511 | #[$attr], |
512 | concat!("Attempts to convert `" , |
513 | stringify!($Int), |
514 | "` to `" , |
515 | stringify!($NonZeroInt), |
516 | "`." )); |
517 | } |
518 | } |
519 | |
520 | // Int -> Non-zero Int |
521 | nzint_impl_try_from_int! { u8, NonZeroU8, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
522 | nzint_impl_try_from_int! { u16, NonZeroU16, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
523 | nzint_impl_try_from_int! { u32, NonZeroU32, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
524 | nzint_impl_try_from_int! { u64, NonZeroU64, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
525 | nzint_impl_try_from_int! { u128, NonZeroU128, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
526 | nzint_impl_try_from_int! { usize, NonZeroUsize, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
527 | nzint_impl_try_from_int! { i8, NonZeroI8, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
528 | nzint_impl_try_from_int! { i16, NonZeroI16, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
529 | nzint_impl_try_from_int! { i32, NonZeroI32, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
530 | nzint_impl_try_from_int! { i64, NonZeroI64, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
531 | nzint_impl_try_from_int! { i128, NonZeroI128, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
532 | nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable (feature = "nzint_try_from_int_conv" , since = "1.46.0" )] } |
533 | |
534 | macro_rules! nzint_impl_try_from_nzint { |
535 | ($From:ty => $To:ty, $doc: expr) => { |
536 | #[stable(feature = "nzint_try_from_nzint_conv" , since = "1.49.0" )] |
537 | impl TryFrom<$From> for $To { |
538 | type Error = TryFromIntError; |
539 | |
540 | // Rustdocs on the impl block show a "[+] show undocumented items" toggle. |
541 | // Rustdocs on functions do not. |
542 | #[doc = $doc] |
543 | #[inline] |
544 | fn try_from(value: $From) -> Result<Self, Self::Error> { |
545 | TryFrom::try_from(value.get()).map(|v| { |
546 | // SAFETY: $From is a NonZero type, so v is not zero. |
547 | unsafe { Self::new_unchecked(v) } |
548 | }) |
549 | } |
550 | } |
551 | }; |
552 | ($To:ty: $($From: ty),*) => {$( |
553 | nzint_impl_try_from_nzint!( |
554 | $From => $To, |
555 | concat!( |
556 | "Attempts to convert `" , |
557 | stringify!($From), |
558 | "` to `" , |
559 | stringify!($To), |
560 | "`." , |
561 | ) |
562 | ); |
563 | )*}; |
564 | } |
565 | |
566 | // Non-zero int -> non-zero unsigned int |
567 | nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
568 | nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
569 | nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
570 | nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
571 | nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize } |
572 | nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize } |
573 | |
574 | // Non-zero int -> non-zero signed int |
575 | nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
576 | nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
577 | nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
578 | nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } |
579 | nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize } |
580 | nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize } |
581 | |