diff --git a/Cargo.toml b/Cargo.toml index efaafc5..9f5bb4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ bundled-sqlcipher-vendored-openssl = ["libsqlite3-sys/bundled-sqlcipher-vendored buildtime_bindgen = ["libsqlite3-sys/buildtime_bindgen"] limits = [] hooks = [] -i128_blob = ["byteorder"] +i128_blob = [] sqlcipher = ["libsqlite3-sys/sqlcipher"] unlock_notify = ["libsqlite3-sys/unlock_notify"] # xSavepoint, xRelease and xRollbackTo: 3.7.7 (2011-06-23) @@ -105,7 +105,6 @@ serde_json = { version = "1.0", optional = true } csv = { version = "1.1", optional = true } url = { version = "2.1", optional = true } lazy_static = { version = "1.4", optional = true } -byteorder = { version = "1.3", features = ["i128"], optional = true } fallible-iterator = "0.2" fallible-streaming-iterator = "0.1" memchr = "2.3" diff --git a/src/error.rs b/src/error.rs index 56807ff..129f697 100644 --- a/src/error.rs +++ b/src/error.rs @@ -202,12 +202,7 @@ impl From for Error { // context. match err { FromSqlError::OutOfRange(val) => Error::IntegralValueOutOfRange(UNKNOWN_COLUMN, val), - #[cfg(feature = "i128_blob")] - FromSqlError::InvalidI128Size(_) => { - Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err)) - } - #[cfg(feature = "uuid")] - FromSqlError::InvalidUuidSize(_) => { + FromSqlError::InvalidBlobSize { .. } => { Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err)) } FromSqlError::Other(source) => { diff --git a/src/functions.rs b/src/functions.rs index 4d90d99..3006a79 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -144,15 +144,7 @@ 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)) - } - #[cfg(feature = "uuid")] - FromSqlError::InvalidUuidSize(_) => { + FromSqlError::InvalidBlobSize { .. } => { Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) } }) diff --git a/src/row.rs b/src/row.rs index 97f4100..675bed1 100644 --- a/src/row.rs +++ b/src/row.rs @@ -288,23 +288,11 @@ impl<'stmt> Row<'stmt> { ), FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i), FromSqlError::Other(err) => { - Error::FromSqlConversionFailure(idx as usize, value.data_type(), err) + Error::FromSqlConversionFailure(idx, value.data_type(), err) } - FromSqlError::InvalidSize(_, _) => { - Error::FromSqlConversionFailure(idx as usize, value.data_type(), Box::new(err)) + FromSqlError::InvalidBlobSize { .. } => { + Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) } - #[cfg(feature = "i128_blob")] - FromSqlError::InvalidI128Size(_) => Error::InvalidColumnType( - idx, - self.stmt.column_name_unwrap(idx).into(), - value.data_type(), - ), - #[cfg(feature = "uuid")] - FromSqlError::InvalidUuidSize(_) => Error::InvalidColumnType( - idx, - self.stmt.column_name_unwrap(idx).into(), - value.data_type(), - ), }) } diff --git a/src/types/from_sql.rs b/src/types/from_sql.rs index 769e875..0f072c9 100644 --- a/src/types/from_sql.rs +++ b/src/types/from_sql.rs @@ -16,21 +16,13 @@ pub enum FromSqlError { 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. - #[cfg(feature = "i128_blob")] - #[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))] - InvalidI128Size(usize), - - /// Error returned when reading a `uuid` from a blob with - /// a size other than 16. Only available when the `uuid` feature is enabled. - #[cfg(feature = "uuid")] - #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))] - InvalidUuidSize(usize), + /// requested type due to a size mismatch. + InvalidBlobSize { + /// The expected size of the blob. + expected_size: usize, + /// The actual size of the blob that was returned. + blob_size: usize, + }, /// An error case available for implementors of the [`FromSql`] trait. Other(Box), @@ -41,10 +33,16 @@ impl PartialEq for FromSqlError { match (self, other) { (FromSqlError::InvalidType, FromSqlError::InvalidType) => true, (FromSqlError::OutOfRange(n1), FromSqlError::OutOfRange(n2)) => n1 == n2, - #[cfg(feature = "i128_blob")] - (FromSqlError::InvalidI128Size(s1), FromSqlError::InvalidI128Size(s2)) => s1 == s2, - #[cfg(feature = "uuid")] - (FromSqlError::InvalidUuidSize(s1), FromSqlError::InvalidUuidSize(s2)) => s1 == s2, + ( + FromSqlError::InvalidBlobSize { + expected_size: es1, + blob_size: bs1, + }, + FromSqlError::InvalidBlobSize { + expected_size: es2, + blob_size: bs2, + }, + ) => es1 == es2 && bs1 == bs2, (..) => false, } } @@ -55,16 +53,15 @@ 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) - } - #[cfg(feature = "uuid")] - FromSqlError::InvalidUuidSize(s) => { - write!(f, "Cannot read UUID value out of {} byte blob", s) + FromSqlError::InvalidBlobSize { + expected_size, + blob_size, + } => { + write!( + f, + "Cannot read {} byte value out of {} byte blob", + expected_size, blob_size + ) } FromSqlError::Other(ref err) => err.fmt(f), } @@ -188,9 +185,10 @@ 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())) + slice.try_into().map_err(|_| FromSqlError::InvalidBlobSize { + expected_size: N, + blob_size: slice.len(), + }) } } @@ -199,15 +197,8 @@ impl FromSql for [u8; N] { impl FromSql for i128 { #[inline] fn column_result(value: ValueRef<'_>) -> FromSqlResult { - use byteorder::{BigEndian, ByteOrder}; - - value.as_blob().and_then(|bytes| { - if bytes.len() == 16 { - Ok(BigEndian::read_i128(bytes) ^ (1i128 << 127)) - } else { - Err(FromSqlError::InvalidI128Size(bytes.len())) - } - }) + let bytes = <[u8; 16]>::column_result(value)?; + Ok(i128::from_be_bytes(bytes) ^ (1i128 << 127)) } } @@ -216,13 +207,8 @@ impl FromSql for i128 { impl FromSql for uuid::Uuid { #[inline] fn column_result(value: ValueRef<'_>) -> FromSqlResult { - value - .as_blob() - .and_then(|bytes| { - uuid::Builder::from_slice(bytes) - .map_err(|_| FromSqlError::InvalidUuidSize(bytes.len())) - }) - .map(|mut builder| builder.build()) + let bytes = <[u8; 16]>::column_result(value)?; + Ok(uuid::Uuid::from_u128(u128::from_be_bytes(bytes))) } } diff --git a/src/types/value.rs b/src/types/value.rs index 9d55809..04c2def 100644 --- a/src/types/value.rs +++ b/src/types/value.rs @@ -45,12 +45,9 @@ impl From for Value { impl From for Value { #[inline] fn from(i: i128) -> Value { - use byteorder::{BigEndian, ByteOrder}; - let mut buf = vec![0u8; 16]; // We store these biased (e.g. with the most significant bit flipped) // so that comparisons with negative numbers work properly. - BigEndian::write_i128(&mut buf, i ^ (1i128 << 127)); - Value::Blob(buf) + Value::Blob(i128::to_be_bytes(i ^ (1i128 << 127)).to_vec()) } } diff --git a/src/vtab/mod.rs b/src/vtab/mod.rs index 4fd3625..929d599 100644 --- a/src/vtab/mod.rs +++ b/src/vtab/mod.rs @@ -600,20 +600,10 @@ impl Values<'_> { FromSqlError::Other(err) => { Error::FromSqlConversionFailure(idx, value.data_type(), err) } - FromSqlError::InvalidSize(_, _) => { + FromSqlError::InvalidBlobSize { .. } => { 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")))] - FromSqlError::InvalidI128Size(_) => { - Error::InvalidColumnType(idx, idx.to_string(), value.data_type()) - } - #[cfg(feature = "uuid")] - #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))] - FromSqlError::InvalidUuidSize(_) => { - Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err)) - } }) }