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