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 new(value: T) -> Self {
33        Passive::Set(value)
34    }
35    pub fn expect(self, msg: &str) -> T {
36        match self {
37            Passive::Set(v) => v,
38            Passive::NotSet => panic!("{}", msg),
39        }
40    }
41    pub fn unwrap(self) -> T {
42        match self {
43            Passive::Set(v) => v,
44            Passive::NotSet => panic!("called `Passive::unwrap()` on a `NotSet` value"),
45        }
46    }
47}
48
49impl<T: AsValue + PartialEq> PartialEq for Passive<T> {
50    fn eq(&self, other: &Self) -> bool {
51        match (self, other) {
52            (Self::Set(lhs), Self::Set(rhs)) => lhs == rhs,
53            _ => mem::discriminant(self) == mem::discriminant(other),
54        }
55    }
56}
57
58impl<T: AsValue + Clone> Clone for Passive<T>
59where
60    T: Clone,
61{
62    fn clone(&self) -> Self {
63        match self {
64            Self::Set(v) => Self::Set(v.clone()),
65            Self::NotSet => Self::NotSet,
66        }
67    }
68}
69
70impl<T: AsValue> From<T> for Passive<T> {
71    fn from(value: T) -> Self {
72        Self::Set(value)
73    }
74}
75
76/// Foreign key reference to another Entity's columns.
77pub struct References<T: Entity> {
78    entity: PhantomData<T>,
79    columns: Box<[ColumnDef]>,
80}
81
82impl<T: Entity> References<T> {
83    pub fn new(columns: Box<[ColumnDef]>) -> Self {
84        Self {
85            columns,
86            entity: Default::default(),
87        }
88    }
89    pub fn table_ref(&self) -> TableRef {
90        T::table().clone()
91    }
92    pub fn columns(&self) -> &[ColumnDef] {
93        &self.columns
94    }
95}