use crate::prelude::*;
use crate::values::{OwnedSQLiteValue, SQLiteValue, SQLiteValueRef};
use drizzle_core::conv::checked_float_to_int;
use drizzle_core::error::DrizzleError;
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used as a SQLite column type",
note = "add #[derive(SQLiteEnum)] for enum types, or use a supported primitive type"
)]
pub trait DrizzleSQLiteColumn: Sized {
type SQLType: drizzle_core::types::DataType;
const SQL_TYPE: &'static str;
fn decode(value: SQLiteValueRef<'_>) -> Result<Self, DrizzleError>;
fn encode(&self) -> SQLiteValue<'_>;
fn encode_owned(self) -> OwnedSQLiteValue {
self.encode().into_owned()
}
}
impl<'a, T> From<T> for SQLiteValue<'a>
where
T: DrizzleSQLiteColumn,
{
fn from(value: T) -> Self {
value.encode_owned().into()
}
}
pub trait FromSQLiteValue: Sized {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError>;
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError>;
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError>;
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError>;
fn from_sqlite_ref(value: SQLiteValueRef<'_>) -> Result<Self, DrizzleError> {
match value {
SQLiteValueRef::Integer(value) => Self::from_sqlite_integer(value),
SQLiteValueRef::Text(value) => Self::from_sqlite_text(value),
SQLiteValueRef::Real(value) => Self::from_sqlite_real(value),
SQLiteValueRef::Blob(value) => Self::from_sqlite_blob(value),
SQLiteValueRef::Null => Self::from_sqlite_null(),
}
}
fn from_sqlite_null() -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"unexpected NULL value".into(),
))
}
#[cfg(feature = "rusqlite")]
fn from_value_ref(value: ::rusqlite::types::ValueRef<'_>) -> Result<Self, DrizzleError> {
let value = SQLiteValueRef::try_from_rusqlite_value_ref(value)?;
Self::from_sqlite_ref(value)
}
}
impl<T> FromSQLiteValue for T
where
T: DrizzleSQLiteColumn,
{
fn from_sqlite_ref(value: SQLiteValueRef<'_>) -> Result<Self, DrizzleError> {
T::decode(value)
}
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
T::decode(SQLiteValueRef::Integer(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
T::decode(SQLiteValueRef::Text(value))
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
T::decode(SQLiteValueRef::Real(value))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
T::decode(SQLiteValueRef::Blob(value))
}
fn from_sqlite_null() -> Result<Self, DrizzleError> {
T::decode(SQLiteValueRef::Null)
}
}
pub trait DrizzleRowByIndex {
fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError>;
}
pub trait DrizzleRowByName: DrizzleRowByIndex {
fn get_column_by_name<T: FromSQLiteValue>(&self, name: &str) -> Result<T, DrizzleError>;
}
macro_rules! impl_from_sqlite_value_int {
(i64) => {
impl FromSQLiteValue for i64 {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(value)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse '{}' as i64: {}", value, e).into())
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
checked_float_to_int(value, "i64")
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError("cannot convert BLOB to i64".into()))
}
}
};
($($ty:ty),+ $(,)?) => {
$(
impl FromSQLiteValue for $ty {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
value.try_into().map_err(|e| {
DrizzleError::ConversionError(
format!("i64 {} out of range for {}: {}", value, stringify!($ty), e).into(),
)
})
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{}' as {}: {}", value, stringify!($ty), e).into()
)
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
checked_float_to_int(value, stringify!($ty))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
concat!("cannot convert BLOB to ", stringify!($ty)).into()
))
}
}
)+
};
}
#[inline]
fn i64_to_f64(i: i64) -> f64 {
let high = i32::try_from(i >> 32).expect("sign-extended high word fits in i32");
let low = u32::try_from(i & 0xFFFF_FFFF).expect("masked low word fits in u32");
f64::from(high) * 4_294_967_296.0_f64 + f64::from(low)
}
impl_from_sqlite_value_int!(i64);
impl_from_sqlite_value_int!(i8, i16, i32, isize, u8, u16, u32, u64, usize);
impl FromSQLiteValue for f64 {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(i64_to_f64(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse '{value}' as f64: {e}").into())
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(value)
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to f64".into(),
))
}
}
fn narrow_to_f32(value: f64) -> Result<f32, DrizzleError> {
format!("{value}").parse::<f32>().map_err(|e| {
DrizzleError::ConversionError(format!("cannot convert REAL {value} to f32: {e}").into())
})
}
impl FromSQLiteValue for f32 {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
narrow_to_f32(i64_to_f64(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse '{value}' as f32: {e}").into())
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
narrow_to_f32(value)
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to f32".into(),
))
}
}
impl FromSQLiteValue for bool {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(value != 0)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
match value.to_lowercase().as_str() {
"true" | "1" | "yes" | "on" => Ok(true),
"false" | "0" | "no" | "off" => Ok(false),
_ => Err(DrizzleError::ConversionError(
format!("cannot parse '{value}' as bool").into(),
)),
}
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(value != 0.0)
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to bool".into(),
))
}
}
impl FromSQLiteValue for String {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(value.to_string())
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Ok(value.to_string())
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(value.to_string())
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Self::from_utf8(value.to_vec()).map_err(|e| {
DrizzleError::ConversionError(format!("invalid UTF-8 in BLOB: {e}").into())
})
}
}
impl FromSQLiteValue for compact_str::CompactString {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(Self::new(value.to_string()))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Ok(Self::new(value))
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(Self::new(value.to_string()))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
let s = String::from_utf8(value.to_vec()).map_err(|e| {
DrizzleError::ConversionError(format!("invalid UTF-8 in BLOB: {e}").into())
})?;
Ok(Self::new(s))
}
}
impl FromSQLiteValue for Box<String> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(Self::new)
}
}
impl FromSQLiteValue for Rc<String> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(Self::new)
}
}
impl FromSQLiteValue for Arc<String> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(Self::new)
}
}
impl FromSQLiteValue for Box<str> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(String::into_boxed_str)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(String::into_boxed_str)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(String::into_boxed_str)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(String::into_boxed_str)
}
}
impl FromSQLiteValue for Rc<str> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(Self::from)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(Self::from)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(Self::from)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(Self::from)
}
}
impl FromSQLiteValue for Arc<str> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
String::from_sqlite_integer(value).map(Self::from)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
String::from_sqlite_text(value).map(Self::from)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
String::from_sqlite_real(value).map(Self::from)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
String::from_sqlite_blob(value).map(Self::from)
}
}
impl FromSQLiteValue for Vec<u8> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(value.to_le_bytes().to_vec())
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Ok(value.as_bytes().to_vec())
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(value.to_le_bytes().to_vec())
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Ok(value.to_vec())
}
}
#[cfg(feature = "bytes")]
impl FromSQLiteValue for bytes::Bytes {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_integer(value).map(Self::from)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_text(value).map(Self::from)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_real(value).map(Self::from)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Ok(Self::copy_from_slice(value))
}
}
#[cfg(feature = "bytes")]
impl FromSQLiteValue for bytes::BytesMut {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_integer(value).map(|v| Self::from(v.as_slice()))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_text(value).map(|v| Self::from(v.as_slice()))
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_real(value).map(|v| Self::from(v.as_slice()))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Ok(Self::from(value))
}
}
#[cfg(feature = "smallvec")]
impl<const N: usize> FromSQLiteValue for smallvec::SmallVec<[u8; N]> {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to SmallVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_text(_value: &str) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert TEXT to SmallVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to SmallVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
let mut out = Self::new();
out.extend_from_slice(value);
Ok(out)
}
}
impl FromSQLiteValue for Box<Vec<u8>> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_blob(value).map(Self::new)
}
}
impl FromSQLiteValue for Rc<Vec<u8>> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_blob(value).map(Self::new)
}
}
impl FromSQLiteValue for Arc<Vec<u8>> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_integer(value).map(Self::new)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_text(value).map(Self::new)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_real(value).map(Self::new)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Vec::<u8>::from_sqlite_blob(value).map(Self::new)
}
}
impl<T: FromSQLiteValue> FromSQLiteValue for Option<T> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
T::from_sqlite_integer(value).map(Some)
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
T::from_sqlite_text(value).map(Some)
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
T::from_sqlite_real(value).map(Some)
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
T::from_sqlite_blob(value).map(Some)
}
fn from_sqlite_null() -> Result<Self, DrizzleError> {
Ok(None)
}
}
#[cfg(feature = "rusqlite")]
impl DrizzleRowByIndex for rusqlite::Row<'_> {
fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
let value_ref = self.get_ref(idx)?;
match value_ref {
rusqlite::types::ValueRef::Integer(i) => T::from_sqlite_integer(i),
rusqlite::types::ValueRef::Text(s) => {
let s = core::str::from_utf8(s).map_err(|e| {
DrizzleError::ConversionError(format!("invalid UTF-8: {e}").into())
})?;
T::from_sqlite_text(s)
}
rusqlite::types::ValueRef::Real(r) => T::from_sqlite_real(r),
rusqlite::types::ValueRef::Blob(b) => T::from_sqlite_blob(b),
rusqlite::types::ValueRef::Null => T::from_sqlite_null(),
}
}
}
#[cfg(feature = "rusqlite")]
impl DrizzleRowByName for rusqlite::Row<'_> {
fn get_column_by_name<T: FromSQLiteValue>(&self, name: &str) -> Result<T, DrizzleError> {
let idx = self.as_ref().column_index(name)?;
DrizzleRowByIndex::get_column(self, idx)
}
}
#[cfg(feature = "libsql")]
impl DrizzleRowByIndex for libsql::Row {
fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
let idx_i32 = i32::try_from(idx).map_err(|e| {
DrizzleError::ConversionError(format!("column index {idx} out of range: {e}").into())
})?;
let value = self.get_value(idx_i32)?;
match value {
libsql::Value::Integer(i) => T::from_sqlite_integer(i),
libsql::Value::Text(ref s) => T::from_sqlite_text(s),
libsql::Value::Real(r) => T::from_sqlite_real(r),
libsql::Value::Blob(ref b) => T::from_sqlite_blob(b),
libsql::Value::Null => T::from_sqlite_null(),
}
}
}
#[cfg(feature = "libsql")]
impl DrizzleRowByName for libsql::Row {
fn get_column_by_name<T: FromSQLiteValue>(&self, name: &str) -> Result<T, DrizzleError> {
let idx = (0..self.column_count())
.find(|&i| self.column_name(i) == Some(name))
.ok_or_else(|| {
DrizzleError::ConversionError(format!("column '{name}' not found").into())
})?;
let idx_usize = usize::try_from(idx).map_err(|e| {
DrizzleError::ConversionError(format!("column index {idx} negative: {e}").into())
})?;
DrizzleRowByIndex::get_column(self, idx_usize)
}
}
#[cfg(feature = "turso")]
impl DrizzleRowByIndex for turso::Row {
fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
let value = self.get_value(idx)?;
if value.is_null() {
T::from_sqlite_null()
} else if let Some(&i) = value.as_integer() {
T::from_sqlite_integer(i)
} else if let Some(s) = value.as_text() {
T::from_sqlite_text(s)
} else if let Some(&r) = value.as_real() {
T::from_sqlite_real(r)
} else if let Some(b) = value.as_blob() {
T::from_sqlite_blob(b)
} else {
Err(DrizzleError::ConversionError(
"unknown SQLite value type".into(),
))
}
}
}
#[cfg(feature = "uuid")]
impl FromSQLiteValue for uuid::Uuid {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to UUID".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse_str(value).map_err(|e| {
DrizzleError::ConversionError(format!("invalid UUID string '{value}': {e}").into())
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to UUID".into(),
))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Self::from_slice(value)
.map_err(|e| DrizzleError::ConversionError(format!("invalid UUID bytes: {e}").into()))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::NaiveDate {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to NaiveDate".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as NaiveDate: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to NaiveDate".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to NaiveDate".into(),
))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::NaiveTime {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to NaiveTime".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as NaiveTime: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to NaiveTime".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to NaiveTime".into(),
))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::NaiveDateTime {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to NaiveDateTime".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as NaiveDateTime: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to NaiveDateTime".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to NaiveDateTime".into(),
))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::DateTime<chrono::FixedOffset> {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to DateTime<FixedOffset>".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse_from_rfc3339(value).map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as DateTime<FixedOffset>: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to DateTime<FixedOffset>".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to DateTime<FixedOffset>".into(),
))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::DateTime<chrono::Utc> {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to DateTime<Utc>".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as DateTime<Utc>: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to DateTime<Utc>".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to DateTime<Utc>".into(),
))
}
}
#[cfg(feature = "time")]
impl FromSQLiteValue for time::Date {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to time::Date".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse(value, &time::format_description::well_known::Iso8601::DATE).map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as time::Date: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to time::Date".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to time::Date".into(),
))
}
}
#[cfg(feature = "time")]
impl FromSQLiteValue for time::Time {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to time::Time".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse(value, &time::format_description::well_known::Iso8601::TIME).map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as time::Time: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to time::Time".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to time::Time".into(),
))
}
}
#[cfg(feature = "time")]
impl FromSQLiteValue for time::PrimitiveDateTime {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to time::PrimitiveDateTime".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse(
value,
&time::format_description::well_known::Iso8601::DATE_TIME,
)
.map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as time::PrimitiveDateTime: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to time::PrimitiveDateTime".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to time::PrimitiveDateTime".into(),
))
}
}
#[cfg(feature = "time")]
impl FromSQLiteValue for time::OffsetDateTime {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to time::OffsetDateTime".into(),
))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::parse(value, &time::format_description::well_known::Rfc3339).map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as time::OffsetDateTime: {e}").into(),
)
})
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to time::OffsetDateTime".into(),
))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to time::OffsetDateTime".into(),
))
}
}
#[cfg(feature = "rust-decimal")]
impl FromSQLiteValue for rust_decimal::Decimal {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(Self::from(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
value.parse().map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse '{value}' as Decimal: {e}").into())
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Self::try_from(value).map_err(|e| {
DrizzleError::ConversionError(
format!("cannot convert REAL {value} to Decimal: {e}").into(),
)
})
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to Decimal".into(),
))
}
}
#[cfg(feature = "chrono")]
impl FromSQLiteValue for chrono::Duration {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(Self::seconds(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
let secs: i64 = value.trim_end_matches('s').parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as chrono::Duration: {e}").into(),
)
})?;
Ok(Self::seconds(secs))
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
let millis: i64 = format!("{:.0}", value * 1000.0).parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot convert REAL {value} to chrono::Duration: {e}").into(),
)
})?;
Ok(Self::milliseconds(millis))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to chrono::Duration".into(),
))
}
}
#[cfg(feature = "time")]
impl FromSQLiteValue for time::Duration {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(Self::seconds(value))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
let secs: i64 = value.trim_end_matches('s').parse().map_err(|e| {
DrizzleError::ConversionError(
format!("cannot parse '{value}' as time::Duration: {e}").into(),
)
})?;
Ok(Self::seconds(secs))
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
Ok(Self::seconds_f64(value))
}
fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert BLOB to time::Duration".into(),
))
}
}
#[cfg(feature = "serde")]
impl FromSQLiteValue for serde_json::Value {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
Ok(Self::Number(value.into()))
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
serde_json::from_str(value).map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse '{value}' as JSON: {e}").into())
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
serde_json::Number::from_f64(value)
.map(serde_json::Value::Number)
.ok_or_else(|| {
DrizzleError::ConversionError(
format!("cannot convert non-finite REAL {value} to JSON").into(),
)
})
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
serde_json::from_slice(value).map_err(|e| {
DrizzleError::ConversionError(format!("cannot parse BLOB as JSON: {e}").into())
})
}
}
#[cfg(feature = "arrayvec")]
impl<const N: usize> FromSQLiteValue for arrayvec::ArrayString<N> {
fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
let s = value.to_string();
Self::from(&s).map_err(|_| {
DrizzleError::ConversionError(
format!(
"String length {} exceeds ArrayString capacity {}",
s.len(),
N
)
.into(),
)
})
}
fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
Self::from(value).map_err(|_| {
DrizzleError::ConversionError(
format!(
"Text length {} exceeds ArrayString capacity {}",
value.len(),
N
)
.into(),
)
})
}
fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
let s = value.to_string();
Self::from(&s).map_err(|_| {
DrizzleError::ConversionError(
format!(
"String length {} exceeds ArrayString capacity {}",
s.len(),
N
)
.into(),
)
})
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
let s = String::from_utf8(value.to_vec())
.map_err(|e| DrizzleError::ConversionError(format!("invalid UTF-8: {e}").into()))?;
Self::from(&s).map_err(|_| {
DrizzleError::ConversionError(
format!(
"String length {} exceeds ArrayString capacity {}",
s.len(),
N
)
.into(),
)
})
}
}
#[cfg(feature = "arrayvec")]
impl<const N: usize> FromSQLiteValue for arrayvec::ArrayVec<u8, N> {
fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert INTEGER to ArrayVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_text(_value: &str) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert TEXT to ArrayVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
Err(DrizzleError::ConversionError(
"cannot convert REAL to ArrayVec<u8>, use BLOB".into(),
))
}
fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
Self::try_from(value).map_err(|_| {
DrizzleError::ConversionError(
format!(
"Blob length {} exceeds ArrayVec capacity {}",
value.len(),
N
)
.into(),
)
})
}
}