tank_core/
relations.rs

1use crate::{AsValue, ColumnDef, Entity, TableRef};
2use rust_decimal::Decimal;
3use std::{marker::PhantomData, mem};
4
5/// Decimal wrapper enforcing compile-time width/scale.
6#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct FixedDecimal<const WIDTH: u8, const SCALE: u8>(pub Decimal);
8
9impl<const W: u8, const S: u8> From<Decimal> for FixedDecimal<W, S> {
10    fn from(value: Decimal) -> Self {
11        Self(value)
12    }
13}
14
15impl<const W: u8, const S: u8> From<FixedDecimal<W, S>> for Decimal {
16    fn from(value: FixedDecimal<W, S>) -> Self {
17        value.0
18    }
19}
20
21/// Wrapper marking whether a column should be considered set or skipped (passive) on INSERT.
22#[derive(Debug, Default)]
23pub enum Passive<T: AsValue> {
24    /// Active value.
25    Set(T),
26    /// Skip during value emission (DEFAULT used by `SqlWriter`).
27    #[default]
28    NotSet,
29}
30
31impl<T: AsValue> Passive<T> {
32    pub fn expect(self, msg: &str) -> T {
33        match self {
34            Passive::Set(v) => v,
35            Passive::NotSet => panic!("{}", msg),
36        }
37    }
38    pub fn unwrap(self) -> T {
39        match self {
40            Passive::Set(v) => v,
41            Passive::NotSet => panic!("called `Passive::unwrap()` on a `NotSet` value"),
42        }
43    }
44}
45
46impl<T: AsValue + PartialEq> PartialEq for Passive<T> {
47    fn eq(&self, other: &Self) -> bool {
48        match (self, other) {
49            (Self::Set(lhs), Self::Set(rhs)) => lhs == rhs,
50            _ => mem::discriminant(self) == mem::discriminant(other),
51        }
52    }
53}
54
55impl<T: AsValue + Clone> Clone for Passive<T>
56where
57    T: Clone,
58{
59    fn clone(&self) -> Self {
60        match self {
61            Self::Set(v) => Self::Set(v.clone()),
62            Self::NotSet => Self::NotSet,
63        }
64    }
65}
66
67impl<T: AsValue> From<T> for Passive<T> {
68    fn from(value: T) -> Self {
69        Self::Set(value)
70    }
71}
72
73/// Foreign key reference to another Entity's columns.
74pub struct References<T: Entity> {
75    entity: PhantomData<T>,
76    columns: Box<[ColumnDef]>,
77}
78
79impl<T: Entity> References<T> {
80    pub fn new(columns: Box<[ColumnDef]>) -> Self {
81        Self {
82            columns,
83            entity: Default::default(),
84        }
85    }
86    pub fn table_ref(&self) -> TableRef {
87        T::table().clone()
88    }
89    pub fn columns(&self) -> &[ColumnDef] {
90        &self.columns
91    }
92}