From 25a622aeaad58f0ef8b0d026cf0ad70de44c35d5 Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Tue, 8 May 2018 07:27:31 +0100 Subject: [PATCH] add conversion between integer types and bool through the TryFrom trait. --- src/libcore/num/mod.rs | 22 ++++++++++++++++++++++ src/libcore/tests/num/mod.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ea652ad811e3c..2489e5fdf2cda 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4206,6 +4206,25 @@ macro_rules! try_from_both_bounded { )*} } +macro_rules! try_bool_from { + ($($source:ty),*) => {$( + #[unstable(feature = "try_from", issue = "33417")] + impl TryFrom<$source> for bool { + type Error = TryFromIntError; + + #[inline] + fn try_from(u: $source) -> Result { + if u == 1 { + Ok(true) + } else if u == 0 { + Ok(false) + } else { + Err(TryFromIntError(())) + } + } + } + )*} +} macro_rules! rev { ($mac:ident, $source:ty, $($target:ty),*) => {$( $mac!($target, $source); @@ -4223,6 +4242,9 @@ try_from_both_bounded!(i32, i16, i8); try_from_both_bounded!(i64, i32, i16, i8); try_from_both_bounded!(i128, i64, i32, i16, i8); +// Integer -> Boolean +try_bool_from! { u8, u16, u32, u64, u128, i8, i16, i32, i64, i128 } + // unsigned-to-signed try_from_upper_bounded!(u8, i8); try_from_upper_bounded!(u16, i8, i16); diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index b5e6a019a228c..f21beb2b792f9 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -527,6 +527,37 @@ assume_usize_width! { test_impl_try_from_signed_to_unsigned_err! { test_try_i128usize, i128, usize } } +/// Conversions to bool is lossy. +/// This checks that we only accept 1 for true and 0 for false. +macro_rules! test_impl_try_bool_from_integers { + ($fn_name:ident, $source: ty) => { + #[test] + fn $fn_name() { + let max = <$source>::max_value(); + let min = <$source>::min_value(); + let one: $source = 1; + let zero: $source = 0; + assert!(>::try_from(max).is_err()); + if min != zero { + assert!(>::try_from(min).is_err()); + } + assert_eq!(true, >::try_from(one).unwrap()); + assert_eq!(false, >::try_from(zero).unwrap()); + } + } +} + +test_impl_try_bool_from_integers! { test_try_bool_from_u8, u8 } +test_impl_try_bool_from_integers! { test_try_bool_from_u16, u16 } +test_impl_try_bool_from_integers! { test_try_bool_from_u32, u32 } +test_impl_try_bool_from_integers! { test_try_bool_from_u64, u64 } +test_impl_try_bool_from_integers! { test_try_bool_from_u128, u128 } +test_impl_try_bool_from_integers! { test_try_bool_from_i8, i8 } +test_impl_try_bool_from_integers! { test_try_bool_from_i16, i16 } +test_impl_try_bool_from_integers! { test_try_bool_from_i32, i32 } +test_impl_try_bool_from_integers! { test_try_bool_from_i64, i64 } +test_impl_try_bool_from_integers! { test_try_bool_from_i128, i128 } + macro_rules! test_float { ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname { // FIXME(nagisa): these tests should test for sign of -0.0