use std::marker::PhantomData;
use rorm_db::row::{DecodeOwned, RowError};
use rorm_db::Row;
pub trait Decoder {
type Result;
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>>;
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>>;
}
impl<D: Decoder> Decoder for &'_ D {
type Result = D::Result;
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
D::by_name(self, row)
}
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
D::by_index(self, row)
}
}
pub struct DirectDecoder<T> {
pub(crate) result: PhantomData<T>,
pub(crate) column: String,
pub(crate) index: usize,
}
impl<T> Decoder for DirectDecoder<T>
where
T: DecodeOwned,
{
type Result = T;
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
row.get(self.column.as_str())
}
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
row.get(self.index)
}
}
pub struct NoopDecoder<T>(pub(crate) PhantomData<T>);
impl<T> Decoder for NoopDecoder<T>
where
T: Default,
{
type Result = T;
fn by_name<'index>(&'index self, _row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
Ok(Default::default())
}
fn by_index<'index>(&'index self, _row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
Ok(Default::default())
}
}
macro_rules! decoder {
($($index:tt : $S:ident,)+) => {
impl<$($S: Decoder),+> Decoder for ($($S,)+) {
type Result = ($(
$S::Result,
)+);
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
Ok(($(
self.$index.by_name(row)?,
)+))
}
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
Ok(($(
self.$index.by_index(row)?,
)+))
}
}
};
}
rorm_macro::impl_tuple!(decoder, 1..33);
pub trait DecoderExt: Decoder + Sized {
fn by_ref(&self) -> &Self {
self
}
fn map<F, U>(self, f: F) -> Map<Self, F>
where
F: Fn(Self::Result) -> U,
{
Map {
decoder: self,
function: f,
}
}
fn optional(self) -> Optional<Self> {
Optional { decoder: self }
}
}
pub struct Map<D, F> {
decoder: D,
function: F,
}
impl<D, F, T> Decoder for Map<D, F>
where
D: Decoder,
F: Fn(D::Result) -> T,
{
type Result = T;
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
self.decoder.by_name(row).map(&self.function)
}
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
self.decoder.by_index(row).map(&self.function)
}
}
pub struct Optional<D> {
decoder: D,
}
impl<D> Decoder for Optional<D>
where
D: Decoder,
{
type Result = Option<D::Result>;
fn by_name<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
match self.decoder.by_name(row) {
Ok(result) => Ok(Some(result)),
Err(RowError::UnexpectedNull { .. }) => Ok(None),
Err(error) => Err(error),
}
}
fn by_index<'index>(&'index self, row: &'_ Row) -> Result<Self::Result, RowError<'index>> {
match self.decoder.by_index(row) {
Ok(result) => Ok(Some(result)),
Err(RowError::UnexpectedNull { .. }) => Ok(None),
Err(error) => Err(error),
}
}
}