#![deny(
future_incompatible,
let_underscore,
keyword_idents,
elided_lifetimes_in_paths,
meta_variable_misuse,
noop_method_call,
pointer_structural_match,
unused_lifetimes,
unused_qualifications,
unsafe_op_in_unsafe_fn,
clippy::undocumented_unsafe_blocks,
clippy::wildcard_dependencies,
clippy::debug_assert_with_mut_call,
clippy::empty_line_after_outer_attr,
clippy::panic,
clippy::unwrap_used,
clippy::expect_used,
clippy::redundant_field_names,
clippy::rest_pat_in_fully_bound_structs,
clippy::unneeded_field_pattern,
clippy::useless_let_if_seq,
clippy::default_union_representation,
clippy::arithmetic_side_effects,
clippy::checked_conversions,
clippy::dbg_macro
)]
#![warn(
clippy::pedantic,
clippy::cargo,
clippy::cloned_instead_of_copied,
clippy::cognitive_complexity
)]
#![allow(clippy::must_use_candidate, clippy::doc_markdown)]
#[cfg(feature = "macros")]
pub mod macros {
pub use typesafe_repository_macro::Id;
}
pub mod prelude {
pub use super::{Add, Get, Identity, IdentityOf, List, Remove, Repository, Save, Update, GetBy, ListBy};
}
#[cfg(feature = "inmemory")]
pub mod inmemory;
#[cfg(feature = "transactional")]
pub mod transactional;
pub trait Repository<V: Identity> {
type Error: Send + 'static;
}
pub use async_ops::*;
pub mod async_ops {
use crate::{Dao, Identity, IdentityBy, IdentityOf, Repository, SelectBy, Selector};
use async_trait::async_trait;
#[async_trait]
pub trait Create<D: Dao<Parent = V>, V: Identity>: Repository<V> {
async fn create(&self, d: D) -> Result<IdentityOf<V>, Self::Error>;
}
#[async_trait]
pub trait Add<V: Identity>: Repository<V> {
async fn add(&self, v: V) -> Result<(), Self::Error>;
}
#[async_trait]
pub trait List<V: Identity>: Repository<V> {
async fn list(&self) -> Result<Vec<V>, Self::Error>;
}
#[async_trait]
pub trait Get<V: Identity>: Repository<V> {
async fn get_one(&self, k: &V::Id) -> Result<Option<V>, Self::Error>;
}
#[async_trait]
pub trait Save<V: Identity>: Repository<V> {
async fn save(&self, v: V) -> Result<(), Self::Error>;
}
#[async_trait]
pub trait Update<V: Identity>: Repository<V> {
async fn update(&self, v: V) -> Result<(), Self::Error>;
}
#[async_trait]
pub trait Remove<V: Identity>: Repository<V> {
async fn remove(&self, k: &V::Id) -> Result<Option<V>, Self::Error>;
}
#[async_trait]
pub trait GetBy<V, S>: Repository<V>
where
V: IdentityBy<S> + Identity,
{
async fn get_by(&self, s: &S) -> Result<Option<V>, Self::Error>;
}
#[async_trait]
pub trait ListBy<V, S>: Repository<V>
where
V: IdentityBy<S> + Identity,
{
async fn list_by(&self, s: &S) -> Result<Vec<V>, Self::Error>;
}
#[async_trait]
pub trait Select<V, S>: Repository<V>
where
V: Identity + SelectBy<S>,
S: Selector,
{
async fn select(&self, s: &S) -> Result<Vec<V>, Self::Error>;
}
#[async_trait]
pub trait Find<V, S>: Repository<V>
where
V: Identity + SelectBy<S>,
S: Selector,
{
async fn find(&self, s: &S) -> Result<Option<V>, Self::Error>;
}
}
pub trait Identity
where
Self: Send,
{
type Id: std::fmt::Debug + Clone;
fn id(&self) -> &Self::Id;
}
pub trait Dao {
type Parent: Identity;
type Args;
fn enrich(self, t: Self::Args) -> Self::Parent;
}
pub trait IdentityBy<T> {
fn id_by(&self) -> T;
}
pub trait SelectBy<S: Selector> {}
pub trait Selector {}
pub type IdentityOf<T> = <T as Identity>::Id;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ValidIdentity<T: Identity>(IdentityOf<T>)
where
IdentityOf<T>: PartialEq + Serialize + DeserializeOwned;
impl<T: Identity> ValidIdentity<T>
where
T::Id: PartialEq + Serialize + DeserializeOwned,
{
pub fn of(t: &T) -> Self {
Self(t.id().clone())
}
pub fn into_inner(self) -> IdentityOf<T> {
self.0
}
pub fn from<P: ValidIdentityProvider<T>>(p: &P) -> Self {
Self(p.get())
}
}
pub trait ValidIdentityProvider<T>
where
T: Identity,
T::Id: PartialEq + Serialize + DeserializeOwned,
{
fn get(&self) -> IdentityOf<T>;
}