#[cfg(feature = "value")]
use crate::ffi::ValueRef;
use crate::{
error::{Error, ErrorCode, Result},
ffi::{self, Fetch as _},
statement::Statement,
types::{Borrowed, ColumnIndex, RowId, Type},
};
#[cfg_attr(
not(feature = "value"),
doc = "A value which can be read from a column."
)]
#[cfg_attr(
feature = "value",
doc = "A value which can be read from a column or function argument."
)]
pub trait Fetch<'r>: Sized {
type Value: ffi::Fetch<'r>;
fn fetch_column<'c>(statement: &'r Statement<'c>, column: ColumnIndex) -> Result<Self> {
let value = unsafe { Self::Value::fetch_column(statement.internal_ref(), column) };
Self::from_value(value)
}
#[cfg(feature = "value")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "functions", feature = "value"))))]
fn fetch_value<'c>(value: &'r ValueRef<'c>) -> Result<Self> {
let value = unsafe { Self::Value::fetch_value(value) };
Self::from_value(value)
}
fn from_value(value: Self::Value) -> Result<Self>;
}
macro_rules! identity {
($($t:ty),+) => {
$(
impl<'r> Fetch<'r> for $t {
type Value = Self;
#[inline]
fn from_value(value: Self::Value) -> Result<Self> {
Ok(value)
}
}
)+
};
($($t:ty),+ ,) => {
identity!($($t),+);
};
}
macro_rules! primitive {
($v:ty => $t:ty) => {
impl<'r> Fetch<'r> for $t {
type Value = $v;
#[inline]
fn from_value(value: Self::Value) -> Result<Self> {
Ok($t::from(value))
}
}
};
($v:ty :> $t:ty) => {
impl<'r> Fetch<'r> for $t {
type Value = $v;
#[inline]
fn from_value(value: Self::Value) -> Result<Self> {
<$t as TryFrom<$v>>::try_from(value).map_err(
#[cold]
|_| Error::new(ErrorCode::SQUIRE_FETCH_RANGE),
)
}
}
};
}
identity!(f64);
primitive!(i32 :> i8);
primitive!(i32 :> u8);
primitive!(i32 :> i16);
primitive!(i32 :> u16);
identity!(i32);
primitive!(i64 :> u32);
#[cfg(target_pointer_width = "32")]
primitive!(i32 :> isize);
#[cfg(target_pointer_width = "64")]
primitive!(i64 :> isize);
primitive!(i64 :> usize);
identity!(i64);
primitive!(i64 :> u64);
identity!(Type);
impl<'r> Fetch<'r> for f32 {
type Value = f64;
#[inline]
fn from_value(value: Self::Value) -> Result<Self> {
let result = value as f32;
if value.is_finite() && result.is_infinite() {
Err(Error::with_detail(
ErrorCode::SQUIRE_FETCH_RANGE,
format!("f64 value {} overflows f32 range", value),
))
} else {
Ok(result)
}
}
}
impl<'r> Fetch<'r> for bool {
type Value = i32;
fn from_value(value: Self::Value) -> Result<Self> {
Ok(value != 0)
}
}
impl<'r> Fetch<'r> for RowId {
type Value = i64;
fn from_value(value: Self::Value) -> Result<Self> {
RowId::new(value).ok_or_else(
#[cold]
|| Error::with_detail(ErrorCode::SQUIRE_FETCH_RANGE, "SQLite row ID cannot be 0"),
)
}
}
impl<'r, 'a> Fetch<'r> for &'a str
where
'r: 'a,
{
type Value = Borrowed<'r, str>;
fn from_value(value: Self::Value) -> Result<Self> {
unsafe { Ok(core::mem::transmute::<&'r str, &'a str>(value.into_inner())) }
}
}
impl<'r, 'a> Fetch<'r> for &'a [u8]
where
'r: 'a,
{
type Value = Borrowed<'r, [u8]>;
fn from_value(value: Self::Value) -> Result<Self> {
unsafe {
Ok(core::mem::transmute::<&'r [u8], &'a [u8]>(
value.into_inner(),
))
}
}
}
impl<'r> Fetch<'r> for String {
type Value = Borrowed<'r, str>;
fn from_value(value: Self::Value) -> Result<Self> {
Ok(value.to_owned())
}
}
impl<'r> Fetch<'r> for Vec<u8> {
type Value = Borrowed<'r, [u8]>;
fn from_value(value: Self::Value) -> Result<Self> {
Ok(value.to_owned())
}
}
impl<'r, T> Fetch<'r> for Option<T>
where
T: Fetch<'r>,
{
type Value = Option<T::Value>;
fn from_value(value: Self::Value) -> Result<Self> {
Ok(match value {
Some(value) => Some(T::from_value(value)?),
None => None,
})
}
}