1use super::TryFrom;
2use crate::num::TryFromIntError;
3
4mod 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")]
15pub 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
21macro_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
38impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
39impl_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
44macro_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
69macro_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`
73values.
74
75# Examples
76
77```
78assert_eq!(", stringify!($target), "::from(true), 1);
79assert_eq!(", stringify!($target), "::from(false), 0);
80```"));
81 };
82}
83
84// Bool -> Any
85impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
86impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
87impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
88impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
89impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
90impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
91impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
92impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
93impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
94impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
95impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
96impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
97
98// Unsigned -> Unsigned
99impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
100impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
101impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
102impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
103impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
104impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
105impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
106impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
107impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
108impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
109impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
110
111// Signed -> Signed
112impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
113impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
114impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
115impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
116impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
117impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
118impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
119impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
120impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
121impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
122impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
123
124// Unsigned -> Signed
125impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
126impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
127impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
128impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
129impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
130impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
131impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
132impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
133impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
134impl_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
139impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
140impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
141impl_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
154impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
155impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
156impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
157impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
158impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
159
160// Unsigned -> Float
161impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
162impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
163impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
164impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
165impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
166
167// Float -> Float
168impl_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")]
172impl 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")]
191impl 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
211macro_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
229macro_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)
251macro_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
273macro_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
296macro_rules! rev {
297 ($mac:ident, $source:ty, $($target:ty),*) => {$(
298 $mac!($target, $source);
299 )*}
300}
301
302// intra-sign conversions
303try_from_upper_bounded!(u16, u8);
304try_from_upper_bounded!(u32, u16, u8);
305try_from_upper_bounded!(u64, u32, u16, u8);
306try_from_upper_bounded!(u128, u64, u32, u16, u8);
307
308try_from_both_bounded!(i16, i8);
309try_from_both_bounded!(i32, i16, i8);
310try_from_both_bounded!(i64, i32, i16, i8);
311try_from_both_bounded!(i128, i64, i32, i16, i8);
312
313// unsigned-to-signed
314try_from_upper_bounded!(u8, i8);
315try_from_upper_bounded!(u16, i8, i16);
316try_from_upper_bounded!(u32, i8, i16, i32);
317try_from_upper_bounded!(u64, i8, i16, i32, i64);
318try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
319
320// signed-to-unsigned
321try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
322try_from_lower_bounded!(i16, u16, u32, u64, u128);
323try_from_lower_bounded!(i32, u32, u64, u128);
324try_from_lower_bounded!(i64, u64, u128);
325try_from_lower_bounded!(i128, u128);
326try_from_both_bounded!(i16, u8);
327try_from_both_bounded!(i32, u16, u8);
328try_from_both_bounded!(i64, u32, u16, u8);
329try_from_both_bounded!(i128, u64, u32, u16, u8);
330
331// usize/isize
332try_from_upper_bounded!(usize, isize);
333try_from_lower_bounded!(isize, usize);
334
335#[cfg(target_pointer_width = "16")]
336mod 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")]
359mod 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")]
385mod 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
411use crate::num::NonZeroI128;
412use crate::num::NonZeroI16;
413use crate::num::NonZeroI32;
414use crate::num::NonZeroI64;
415use crate::num::NonZeroI8;
416use crate::num::NonZeroIsize;
417use crate::num::NonZeroU128;
418use crate::num::NonZeroU16;
419use crate::num::NonZeroU32;
420use crate::num::NonZeroU64;
421use crate::num::NonZeroU8;
422use crate::num::NonZeroUsize;
423
424macro_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
453nzint_impl_from! { NonZeroU8, NonZeroU16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
454nzint_impl_from! { NonZeroU8, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
455nzint_impl_from! { NonZeroU8, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
456nzint_impl_from! { NonZeroU8, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
457nzint_impl_from! { NonZeroU8, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
458nzint_impl_from! { NonZeroU16, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
459nzint_impl_from! { NonZeroU16, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
460nzint_impl_from! { NonZeroU16, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
461nzint_impl_from! { NonZeroU16, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
462nzint_impl_from! { NonZeroU32, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
463nzint_impl_from! { NonZeroU32, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
464nzint_impl_from! { NonZeroU64, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
465
466// Non-zero Signed -> Non-zero Signed
467nzint_impl_from! { NonZeroI8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
468nzint_impl_from! { NonZeroI8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
469nzint_impl_from! { NonZeroI8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
470nzint_impl_from! { NonZeroI8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
471nzint_impl_from! { NonZeroI8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
472nzint_impl_from! { NonZeroI16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
473nzint_impl_from! { NonZeroI16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
474nzint_impl_from! { NonZeroI16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
475nzint_impl_from! { NonZeroI16, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
476nzint_impl_from! { NonZeroI32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
477nzint_impl_from! { NonZeroI32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
478nzint_impl_from! { NonZeroI64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
479
480// NonZero UnSigned -> Non-zero Signed
481nzint_impl_from! { NonZeroU8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
482nzint_impl_from! { NonZeroU8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
483nzint_impl_from! { NonZeroU8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
484nzint_impl_from! { NonZeroU8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
485nzint_impl_from! { NonZeroU8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
486nzint_impl_from! { NonZeroU16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
487nzint_impl_from! { NonZeroU16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
488nzint_impl_from! { NonZeroU16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
489nzint_impl_from! { NonZeroU32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
490nzint_impl_from! { NonZeroU32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
491nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
492
493macro_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
521nzint_impl_try_from_int! { u8, NonZeroU8, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
522nzint_impl_try_from_int! { u16, NonZeroU16, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
523nzint_impl_try_from_int! { u32, NonZeroU32, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
524nzint_impl_try_from_int! { u64, NonZeroU64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
525nzint_impl_try_from_int! { u128, NonZeroU128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
526nzint_impl_try_from_int! { usize, NonZeroUsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
527nzint_impl_try_from_int! { i8, NonZeroI8, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
528nzint_impl_try_from_int! { i16, NonZeroI16, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
529nzint_impl_try_from_int! { i32, NonZeroI32, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
530nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
531nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
532nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
533
534macro_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
567nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
568nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
569nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
570nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
571nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize }
572nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize }
573
574// Non-zero int -> non-zero signed int
575nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
576nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
577nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
578nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
579nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize }
580nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize }
581