use crate::database::Database;
use crate::decode::Decode;
use crate::types::{Type, TypeInfo};
use crate::value::{HasRawValue, RawValue};
pub trait ColumnIndex<'c, R>
where
Self: private_column_index::Sealed,
R: Row<'c> + ?Sized,
{
fn index(&self, row: &R) -> crate::Result<usize>;
}
impl<'c, R, I> ColumnIndex<'c, R> for &'_ I
where
R: Row<'c>,
I: ColumnIndex<'c, R> + ?Sized,
{
#[inline]
fn index(&self, row: &R) -> crate::Result<usize> {
(**self).index(row)
}
}
mod private_column_index {
pub trait Sealed {}
impl Sealed for usize {}
impl Sealed for str {}
impl<T> Sealed for &'_ T where T: Sealed + ?Sized {}
}
pub trait Row<'c>
where
Self: private_row::Sealed + Unpin + Send + Sync,
{
type Database: Database;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
fn len(&self) -> usize;
#[inline]
fn get<T, I>(&self, index: I) -> T
where
T: Type<Self::Database>,
I: ColumnIndex<'c, Self>,
T: Decode<'c, Self::Database>,
{
self.try_get::<T, I>(index).unwrap()
}
#[inline]
fn get_unchecked<T, I>(&self, index: I) -> T
where
T: Type<Self::Database>,
I: ColumnIndex<'c, Self>,
T: Decode<'c, Self::Database>,
{
self.try_get_unchecked::<T, I>(index).unwrap()
}
fn try_get<T, I>(&self, index: I) -> crate::Result<T>
where
T: Type<Self::Database>,
I: ColumnIndex<'c, Self>,
T: Decode<'c, Self::Database>,
{
let value = self.try_get_raw(index)?;
if let Some(expected_ty) = value.type_info() {
if !expected_ty.compatible(&T::type_info()) {
return Err(crate::Error::mismatched_types::<Self::Database, T>(
expected_ty,
));
}
}
T::decode(value)
}
#[inline]
fn try_get_unchecked<T, I>(&self, index: I) -> crate::Result<T>
where
T: Type<Self::Database>,
I: ColumnIndex<'c, Self>,
T: Decode<'c, Self::Database>,
{
self.try_get_raw(index).and_then(T::decode)
}
#[doc(hidden)]
fn try_get_raw<I>(
&self,
index: I,
) -> crate::Result<<Self::Database as HasRawValue<'c>>::RawValue>
where
I: ColumnIndex<'c, Self>;
}
pub(crate) mod private_row {
pub trait Sealed {}
}
pub trait HasRow<'c> {
type Database: Database;
type Row: Row<'c, Database = Self::Database>;
}
pub trait FromRow<'c, R>
where
Self: Sized,
R: Row<'c>,
{
#[allow(missing_docs)]
fn from_row(row: &R) -> crate::Result<Self>;
}
#[allow(unused_macros)]
macro_rules! impl_from_row_for_tuple {
($db:ident, $r:ident; $( ($idx:tt) -> $T:ident );+;) => {
impl<'c, $($T,)+> crate::row::FromRow<'c, $r<'c>> for ($($T,)+)
where
$($T: 'c,)+
$($T: crate::types::Type<$db>,)+
$($T: crate::decode::Decode<'c, $db>,)+
{
#[inline]
fn from_row(row: &$r<'c>) -> crate::Result<Self> {
use crate::row::Row;
Ok(($(row.try_get($idx as usize)?,)+))
}
}
};
}
#[allow(unused_macros)]
macro_rules! impl_from_row_for_tuples {
($db:ident, $r:ident) => {
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
(4) -> T5;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
(4) -> T5;
(5) -> T6;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
(4) -> T5;
(5) -> T6;
(6) -> T7;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
(4) -> T5;
(5) -> T6;
(6) -> T7;
(7) -> T8;
);
impl_from_row_for_tuple!($db, $r;
(0) -> T1;
(1) -> T2;
(2) -> T3;
(3) -> T4;
(4) -> T5;
(5) -> T6;
(6) -> T7;
(7) -> T8;
(8) -> T9;
);
};
}
#[allow(unused_macros)]
macro_rules! impl_map_row_for_row {
($DB:ident, $R:ident) => {
impl<O: Unpin, F> crate::query::MapRow<$DB> for F
where
F: for<'c> FnMut($R<'c>) -> O,
{
type Output = O;
fn map_row(&mut self, row: $R) -> O {
(self)(row)
}
}
impl<O: Unpin, F> crate::query::TryMapRow<$DB> for F
where
F: for<'c> FnMut($R<'c>) -> crate::Result<O>,
{
type Output = O;
fn try_map_row(&mut self, row: $R) -> crate::Result<O> {
(self)(row)
}
}
};
}
#[allow(unused_macros)]
macro_rules! impl_from_row_for_row {
($R:ident) => {
impl<'c> crate::row::FromRow<'c, $R<'c>> for $R<'c> {
#[inline]
fn from_row(row: $R<'c>) -> crate::Result<Self> {
Ok(row)
}
}
};
}