use toasty::{
codegen_support::index::IndexableField,
schema::{Field, Load},
stmt::{Assign, Assignment, Expr, IntoExpr, List, Path},
};
use toasty_core::{
Error,
stmt::{self, Assignments, Projection, Value},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct TenantId(uuid::Uuid);
impl TenantId {
pub fn get(self) -> uuid::Uuid {
self.0
}
}
impl From<uuid::Uuid> for TenantId {
fn from(id: uuid::Uuid) -> Self {
Self(id)
}
}
impl std::fmt::Display for TenantId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl std::str::FromStr for TenantId {
type Err = uuid::Error;
fn from_str(text: &str) -> Result<Self, Self::Err> {
uuid::Uuid::from_str(text).map(Self)
}
}
impl Load for TenantId {
type Output = Self;
fn ty() -> stmt::Type {
stmt::Type::Uuid
}
fn load(value: stmt::Value) -> Result<Self::Output, Error> {
match value {
stmt::Value::Uuid(id) => Ok(Self(id)),
_ => Err(Error::type_conversion(value, "TenantId")),
}
}
fn reload(target: &mut Self::Output, value: stmt::Value) -> Result<(), Error> {
*target = Self::load(value)?;
Ok(())
}
}
impl Field for TenantId {
type ExprTarget = Self;
type Path<Origin> = Path<Origin, Self>;
type ListPath<Origin> = Path<Origin, List<Self::ExprTarget>>;
type Update<'a> = ();
type Inner = Self;
fn new_path<Origin>(path: Path<Origin, Self>) -> Self::Path<Origin> {
path
}
fn new_list_path<Origin>(path: Path<Origin, List<Self::ExprTarget>>) -> Self::ListPath<Origin> {
path
}
fn new_update<'a>(
_assignments: &'a mut Assignments,
_projection: Projection,
) -> Self::Update<'a> {
}
fn key_constraint<Origin>(&self, target: Path<Origin, Self::Inner>) -> Expr<bool> {
target.eq(*self)
}
}
impl IndexableField for TenantId {}
impl IntoExpr<TenantId> for TenantId {
fn into_expr(self) -> Expr<TenantId> {
tenant_expr(self.0)
}
fn by_ref(&self) -> Expr<TenantId> {
tenant_expr(self.0)
}
}
impl Assign<TenantId> for TenantId {
fn into_assignment(self) -> Assignment<TenantId> {
toasty::stmt::set(IntoExpr::<TenantId>::into_expr(self))
}
}
fn tenant_expr(id: uuid::Uuid) -> Expr<TenantId> {
Expr::from_untyped(stmt::Expr::Value(Value::Uuid(id)))
}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a tenant column",
label = "not a tenant column",
note = "type the model's tenant field as `TenantId`, or `Option<TenantId>` for a nullable one"
)]
pub trait TenantColumn: Sized + Field + IntoExpr<Self> + Send + Sync + 'static {
fn from_tenant(id: uuid::Uuid) -> Self;
}
impl TenantColumn for TenantId {
fn from_tenant(id: uuid::Uuid) -> Self {
Self(id)
}
}
impl TenantColumn for Option<TenantId> {
fn from_tenant(id: uuid::Uuid) -> Self {
Some(TenantId(id))
}
}