use std::borrow::Cow;
use std::rc::Rc;
use std::sync::Arc;
use crate::database::Database;
use crate::error::BoxDynError;
use crate::value::ValueRef;
pub trait Decode<'r, DB: Database>: Sized {
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError>;
}
impl<'r, DB, T> Decode<'r, DB> for Option<T>
where
DB: Database,
T: Decode<'r, DB>,
{
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
if value.is_null() {
Ok(None)
} else {
Ok(Some(T::decode(value)?))
}
}
}
macro_rules! impl_decode_for_smartpointer {
($smart_pointer:tt) => {
impl<'r, DB, T> Decode<'r, DB> for $smart_pointer<T>
where
DB: Database,
T: Decode<'r, DB>,
{
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
Ok(Self::new(T::decode(value)?))
}
}
impl<'r, DB> Decode<'r, DB> for $smart_pointer<str>
where
DB: Database,
&'r str: Decode<'r, DB>,
{
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
let ref_str = <&str as Decode<DB>>::decode(value)?;
Ok(ref_str.into())
}
}
impl<'r, DB> Decode<'r, DB> for $smart_pointer<[u8]>
where
DB: Database,
Vec<u8>: Decode<'r, DB>,
{
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
let bytes = <Vec<u8> as Decode<DB>>::decode(value)?;
Ok(bytes.into())
}
}
};
}
impl_decode_for_smartpointer!(Arc);
impl_decode_for_smartpointer!(Box);
impl_decode_for_smartpointer!(Rc);
impl<'r, DB, T> Decode<'r, DB> for Cow<'_, T>
where
DB: Database,
T: ToOwned + ?Sized,
<T as ToOwned>::Owned: Decode<'r, DB>,
{
fn decode(value: <DB as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
<<T as ToOwned>::Owned as Decode<DB>>::decode(value).map(Cow::Owned)
}
}