use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
#[diagnostic::on_unimplemented(
note = "Type `{Self}` does not implement the `Model` trait which is required for database operations",
label = "this type does not implement `Model`",
message = "`{Self}` must implement `Model` to define how to identify database records"
)]
pub trait Model: Send + Sync {
type Id: Send;
fn get_id(&self) -> Option<Self::Id>;
fn has_id(&self) -> bool {
self.get_id().is_some()
}
}
impl<M> Model for Vec<M>
where
M: Model + Send + Sync,
{
type Id = Vec<Option<M::Id>>;
#[inline]
fn get_id(&self) -> Option<Self::Id> {
let mut ids = Vec::new();
for m in self {
ids.push(m.get_id())
}
Some(ids)
}
}
impl<M> Model for Option<M>
where
M: Model + Send + Sync,
{
type Id = M::Id;
#[inline]
fn get_id(&self) -> Option<Self::Id> {
if let Some(m) = self {
m.get_id()
} else {
None
}
}
}
impl<M, E> Model for Result<M, E>
where
M: Model + Send + Sync,
E: Send + Sync,
{
type Id = M::Id;
#[inline]
fn get_id(&self) -> Option<Self::Id> {
if let Ok(m) = self {
m.get_id()
} else {
None
}
}
}
impl<K, V> Model for HashMap<K, V>
where
K: Eq + Hash + Clone + Send + Sync,
V: Model + Send + Sync,
{
type Id = HashMap<K, Option<V::Id>>;
#[inline]
fn get_id(&self) -> Option<Self::Id> {
Some(self.iter().map(|(k, v)| (k.clone(), v.get_id())).collect())
}
}
impl<K, V> Model for BTreeMap<K, V>
where
K: Ord + Clone + Send + Sync,
V: Model + Send + Sync,
{
type Id = BTreeMap<K, Option<V::Id>>;
#[inline]
fn get_id(&self) -> Option<Self::Id> {
Some(self.iter().map(|(k, v)| (k.clone(), v.get_id())).collect())
}
}