@@ -39,63 +39,52 @@ impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i12
3939impl_float_to_int ! ( f64 => u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ) ;
4040impl_float_to_int ! ( f128 => u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ) ;
4141
42- // Conversion traits for primitive integer and float types
43- // Conversions T -> T are covered by a blanket impl and therefore excluded
44- // Some conversions from and to usize/isize are not implemented due to portability concerns
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`
4572macro_rules! impl_from {
46- ( bool => $Int: ty $( , ) ?) => {
47- impl_from!(
48- bool => $Int,
49- #[ stable( feature = "from_bool" , since = "1.28.0" ) ] ,
50- concat!(
51- "Converts a [`bool`] to [`" , stringify!( $Int) , "`] losslessly.\n " ,
52- "The resulting value is `0` for `false` and `1` for `true` values.\n " ,
53- "\n " ,
54- "# Examples\n " ,
55- "\n " ,
56- "```\n " ,
57- "assert_eq!(" , stringify!( $Int) , "::from(true), 1);\n " ,
58- "assert_eq!(" , stringify!( $Int) , "::from(false), 0);\n " ,
59- "```\n " ,
60- ) ,
61- ) ;
62- } ;
63- ( $Small: ty => $Large: ty, #[ $attr: meta] $( , ) ?) => {
64- impl_from!(
65- $Small => $Large,
66- #[ $attr] ,
67- concat!( "Converts [`" , stringify!( $Small) , "`] to [`" , stringify!( $Large) , "`] losslessly." ) ,
68- ) ;
69- } ;
70- ( $Small: ty => $Large: ty, #[ $attr: meta] , $doc: expr $( , ) ?) => {
73+ ( $small: ty => $large: ty, #[ $attr: meta] ) => {
7174 #[ $attr]
7275 #[ rustc_const_unstable( feature = "const_convert" , issue = "143773" ) ]
73- impl const From <$Small> for $Large {
74- // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
75- // Rustdocs on functions do not.
76- #[ doc = $doc]
76+ impl const From <$small> for $large {
77+ #[ doc = concat!( "Converts from [`" , stringify!( $small) , "`] to [`" , stringify!( $large) , "`] losslessly." ) ]
7778 #[ inline( always) ]
78- fn from( small: $Small) -> Self {
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 ) ;
7982 small as Self
8083 }
8184 }
82- } ;
85+ }
8386}
8487
85- // boolean -> integer
86- impl_from ! ( bool => u8 ) ;
87- impl_from ! ( bool => u16 ) ;
88- impl_from ! ( bool => u32 ) ;
89- impl_from ! ( bool => u64 ) ;
90- impl_from ! ( bool => u128 ) ;
91- impl_from ! ( bool => usize ) ;
92- impl_from ! ( bool => i8 ) ;
93- impl_from ! ( bool => i16 ) ;
94- impl_from ! ( bool => i32 ) ;
95- impl_from ! ( bool => i64 ) ;
96- impl_from ! ( bool => i128 ) ;
97- impl_from ! ( bool => isize ) ;
98-
9988// unsigned integer -> unsigned integer
10089impl_from ! ( u8 => u16 , #[ stable( feature = "lossless_int_conv" , since = "1.5.0" ) ] ) ;
10190impl_from ! ( u8 => u32 , #[ stable( feature = "lossless_int_conv" , since = "1.5.0" ) ] ) ;
@@ -338,12 +327,48 @@ macro_rules! impl_try_from_both_bounded {
338327 ) * }
339328}
340329
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+
341362macro_rules! rev {
342363 ( $mac: ident, $source: ty => $( $target: ty) ,+) => { $(
343364 $mac!( $target => $source) ;
344365 ) * }
345366}
346367
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+
347372// unsigned integer -> unsigned integer
348373impl_try_from_upper_bounded ! ( u16 => u8 ) ;
349374impl_try_from_upper_bounded ! ( u32 => u8 , u16 ) ;
0 commit comments