diff --git a/src/functions.rs b/src/functions.rs index 4240b0d..4d90d99 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -144,6 +144,9 @@ impl Context<'_> { FromSqlError::Other(err) => { Error::FromSqlConversionFailure(idx, value.data_type(), err) } + FromSqlError::InvalidSize(_, _) => { + Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) + } #[cfg(feature = "i128_blob")] FromSqlError::InvalidI128Size(_) => { Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) diff --git a/src/row.rs b/src/row.rs index 826aab9..97f4100 100644 --- a/src/row.rs +++ b/src/row.rs @@ -290,6 +290,9 @@ impl<'stmt> Row<'stmt> { FromSqlError::Other(err) => { Error::FromSqlConversionFailure(idx as usize, value.data_type(), err) } + FromSqlError::InvalidSize(_, _) => { + Error::FromSqlConversionFailure(idx as usize, value.data_type(), Box::new(err)) + } #[cfg(feature = "i128_blob")] FromSqlError::InvalidI128Size(_) => Error::InvalidColumnType( idx, diff --git a/src/types/from_sql.rs b/src/types/from_sql.rs index cefe2cb..769e875 100644 --- a/src/types/from_sql.rs +++ b/src/types/from_sql.rs @@ -15,6 +15,10 @@ pub enum FromSqlError { /// requested type. OutOfRange(i64), + /// Error when the blob result returned by SQLite cannot be stored into the + /// requested type due to a size mismatch. (type size, blob size) + InvalidSize(usize, usize), + /// Error returned when reading an `i128` from a /// blob with a size other than 16. Only available when the `i128_blob` /// feature is enabled. @@ -51,6 +55,9 @@ impl fmt::Display for FromSqlError { match *self { FromSqlError::InvalidType => write!(f, "Invalid type"), FromSqlError::OutOfRange(i) => write!(f, "Value {} out of range", i), + FromSqlError::InvalidSize(i, j) => { + write!(f, "Cannot read {} byte value out of {} byte blob", i, j) + } #[cfg(feature = "i128_blob")] FromSqlError::InvalidI128Size(s) => { write!(f, "Cannot read 128bit value out of {} byte blob", s) @@ -177,6 +184,16 @@ impl FromSql for Vec { } } +impl FromSql for [u8; N] { + #[inline] + fn column_result(value: ValueRef<'_>) -> FromSqlResult { + let slice = value.as_blob()?; + slice + .try_into() + .map_err(|_| FromSqlError::InvalidSize(N, slice.len())) + } +} + #[cfg(feature = "i128_blob")] #[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))] impl FromSql for i128 { diff --git a/src/types/to_sql.rs b/src/types/to_sql.rs index d6d987c..2445339 100644 --- a/src/types/to_sql.rs +++ b/src/types/to_sql.rs @@ -224,6 +224,13 @@ impl ToSql for Vec { } } +impl ToSql for [u8; N] { + #[inline] + fn to_sql(&self) -> Result> { + Ok(ToSqlOutput::from(&self[..])) + } +} + impl ToSql for [u8] { #[inline] fn to_sql(&self) -> Result> { @@ -265,6 +272,15 @@ mod test { is_to_sql::(); } + #[test] + fn test_u8_array() { + let a: [u8; 99] = [0u8; 99]; + let _a: &[&dyn ToSql] = crate::params![a]; + let r = ToSql::to_sql(&a); + + assert!(r.is_ok()); + } + #[test] fn test_cow_str() { use std::borrow::Cow; diff --git a/src/vtab/mod.rs b/src/vtab/mod.rs index ba610fa..4fd3625 100644 --- a/src/vtab/mod.rs +++ b/src/vtab/mod.rs @@ -600,6 +600,9 @@ impl Values<'_> { FromSqlError::Other(err) => { Error::FromSqlConversionFailure(idx, value.data_type(), err) } + FromSqlError::InvalidSize(_, _) => { + Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) + } FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i), #[cfg(feature = "i128_blob")] #[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]