From 846a59695c820fa9de8f1611e2590fb884544057 Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Sun, 22 Jan 2017 19:40:48 -0500 Subject: [PATCH] Add range-checked FromSql impls for i8, i16, u8, u16, u32. --- src/types/from_sql.rs | 70 +++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/types/from_sql.rs b/src/types/from_sql.rs index da4588f..32ad3a3 100644 --- a/src/types/from_sql.rs +++ b/src/types/from_sql.rs @@ -53,17 +53,28 @@ pub trait FromSql: Sized { fn column_result(value: ValueRef) -> FromSqlResult; } -impl FromSql for i32 { - fn column_result(value: ValueRef) -> FromSqlResult { - i64::column_result(value).and_then(|i| { - if i < i32::min_value() as i64 || i > i32::max_value() as i64 { - Err(FromSqlError::OutOfRange(i)) - } else { - Ok(i as i32) +macro_rules! from_sql_integral( + ($t:ident) => ( + impl FromSql for $t { + fn column_result(value: ValueRef) -> FromSqlResult { + i64::column_result(value).and_then(|i| { + if i < $t::min_value() as i64 || i > $t::max_value() as i64 { + Err(FromSqlError::OutOfRange(i)) + } else { + Ok(i as $t) + } + }) } - }) - } -} + } + ) +); + +from_sql_integral!(i8); +from_sql_integral!(i16); +from_sql_integral!(i32); +from_sql_integral!(u8); +from_sql_integral!(u16); +from_sql_integral!(u32); impl FromSql for i64 { fn column_result(value: ValueRef) -> FromSqlResult { @@ -120,6 +131,7 @@ impl FromSql for Value { #[cfg(test)] mod test { use {Connection, Error}; + use super::FromSql; fn checked_memory_handle() -> Connection { Connection::open_in_memory().unwrap() @@ -129,23 +141,31 @@ mod test { fn test_integral_ranges() { let db = checked_memory_handle(); - fn assert_out_of_range_error(err: Error, value: i64) { - match err { - Error::IntegralValueOutOfRange(_, bad) => assert_eq!(bad, value), - _ => panic!("unexpected error {}", err), + fn check_ranges(db: &Connection, out_of_range: &[i64], in_range: &[i64]) + where T: Into + FromSql + ::std::fmt::Debug + { + for n in out_of_range { + let err = db.query_row("SELECT ?", &[n], |r| r.get_checked::<_, T>(0)) + .unwrap() + .unwrap_err(); + match err { + Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value), + _ => panic!("unexpected error: {}", err), + } + } + for n in in_range { + assert_eq!(*n, + db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0)).unwrap().into()); } } - // i32 - for bad in &[-2147483649, 2147483648] { - let err = db.query_row("SELECT ?", &[bad], |r| r.get_checked::<_, i32>(0)) - .unwrap() - .unwrap_err(); - assert_out_of_range_error(err, *bad); - } - for good in &[-2147483648, 2147483647] { - assert_eq!(*good, - db.query_row("SELECT ?", &[good], |r| r.get::<_, i32>(0)).unwrap()); - } + check_ranges::(&db, &[-129, 128], &[-128, 0, 1, 127]); + check_ranges::(&db, &[-32769, 32768], &[-32768, -1, 0, 1, 32767]); + check_ranges::(&db, + &[-2147483649, 2147483648], + &[-2147483648, -1, 0, 1, 2147483647]); + check_ranges::(&db, &[-2, -1, 256], &[0, 1, 255]); + check_ranges::(&db, &[-2, -1, 65536], &[0, 1, 65535]); + check_ranges::(&db, &[-2, -1, 4294967296], &[0, 1, 4294967295]); } }