1use std::collections::hash_map::DefaultHasher;
3use std::fmt::{Display, Formatter};
4use std::hash::{Hash, Hasher};
5
6use ordered_float::OrderedFloat;
7use serde::{Deserialize, Serialize};
8use strum::EnumIter;
9
10#[derive(Serialize, Deserialize, Debug, Clone, Hash)]
12#[serde(rename_all = "PascalCase")]
13pub struct InternalModelFormat {
14    pub models: Vec<Model>,
16}
17
18#[derive(Serialize, Deserialize, Debug, Clone)]
20#[serde(rename_all = "PascalCase")]
21pub struct Model {
22    pub name: String,
24
25    pub fields: Vec<Field>,
27
28    #[serde(default)]
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub source_defined_at: Option<Source>,
32}
33
34impl PartialEq for Model {
35    fn eq(&self, other: &Self) -> bool {
36        self.name == other.name && self.fields == other.fields
37    }
38}
39
40impl Hash for Model {
41    fn hash<H: Hasher>(&self, state: &mut H) {
42        self.fields.hash(state);
43        self.name.hash(state);
44    }
45
46    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
47    where
48        Self: Sized,
49    {
50        data.iter().for_each(|x| x.hash(state));
51    }
52}
53
54#[derive(Serialize, Deserialize, Debug, Clone)]
56#[serde(rename_all = "PascalCase")]
57pub struct Field {
58    pub name: String,
60
61    #[serde(rename = "Type")]
63    pub db_type: DbType,
64
65    pub annotations: Vec<Annotation>,
67
68    #[serde(default)]
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub source_defined_at: Option<Source>,
72}
73
74impl PartialEq for Field {
75    fn eq(&self, other: &Self) -> bool {
76        self.name == other.name
77            && self.db_type == other.db_type
78            && self.annotations == other.annotations
79    }
80}
81
82impl Hash for Field {
83    fn hash<H: Hasher>(&self, state: &mut H) {
84        self.name.hash(state);
85        self.annotations.hash(state);
86        self.db_type.hash(state);
87    }
88
89    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
90    where
91        Self: Sized,
92    {
93        data.iter().for_each(|x| x.hash(state));
94    }
95}
96
97#[derive(Serialize, Deserialize, Debug, Clone, Hash)]
100#[serde(rename_all = "PascalCase")]
101pub struct Source {
102    pub file: String,
104    pub line: usize,
106    pub column: usize,
108}
109
110#[allow(missing_docs)]
112#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, PartialEq, Eq)]
113#[serde(rename_all = "lowercase")]
114pub enum DbType {
115    VarChar,
116    Binary,
117    Int8,
118    Int16,
119    Int32,
120    Int64,
121    #[serde(rename = "float_number")]
122    Float,
123    #[serde(rename = "double_number")]
124    Double,
125    Boolean,
126    Date,
127    DateTime,
128    Timestamp,
129    Time,
130    Choices,
131    Uuid,
132    MacAddress,
133    IpNetwork,
134    BitVec,
135}
136
137#[non_exhaustive]
139#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, EnumIter)]
140#[serde(tag = "Type", content = "Value")]
141#[serde(rename_all = "snake_case")]
142pub enum Annotation {
143    AutoCreateTime,
146    AutoUpdateTime,
149    AutoIncrement,
151    Choices(Vec<String>),
153    DefaultValue(DefaultValue),
155    Index(Option<IndexValue>),
157    MaxLength(i32),
159    NotNull,
161    PrimaryKey,
163    Unique,
165    ForeignKey(ForeignKey),
167}
168
169impl Annotation {
170    pub fn eq_shallow(&self, other: &Self) -> bool {
181        match (self, other) {
182            (Annotation::AutoCreateTime, Annotation::AutoCreateTime) => true,
183            (Annotation::AutoCreateTime, _) => false,
184            (Annotation::AutoUpdateTime, Annotation::AutoUpdateTime) => true,
185            (Annotation::AutoUpdateTime, _) => false,
186            (Annotation::AutoIncrement, Annotation::AutoIncrement) => true,
187            (Annotation::AutoIncrement, _) => false,
188            (Annotation::Choices(_), Annotation::Choices(_)) => true,
189            (Annotation::Choices(_), _) => false,
190            (Annotation::DefaultValue(_), Annotation::DefaultValue(_)) => true,
191            (Annotation::DefaultValue(_), _) => false,
192            (Annotation::Index(_), Annotation::Index(_)) => true,
193            (Annotation::Index(_), _) => false,
194            (Annotation::MaxLength(_), Annotation::MaxLength(_)) => true,
195            (Annotation::MaxLength(_), _) => false,
196            (Annotation::NotNull, Annotation::NotNull) => true,
197            (Annotation::NotNull, _) => false,
198            (Annotation::PrimaryKey, Annotation::PrimaryKey) => true,
199            (Annotation::PrimaryKey, _) => false,
200            (Annotation::Unique, Annotation::Unique) => true,
201            (Annotation::Unique, _) => false,
202            (Annotation::ForeignKey(_), Annotation::ForeignKey(_)) => true,
203            (Annotation::ForeignKey(_), _) => false,
204        }
205    }
206
207    pub fn hash_shallow(&self) -> u64 {
218        let mut state = DefaultHasher::new();
219        match self {
220            Annotation::AutoCreateTime => state.write_i8(0),
221            Annotation::AutoUpdateTime => state.write_i8(1),
222            Annotation::AutoIncrement => state.write_i8(2),
223            Annotation::Choices(_) => state.write_i8(3),
224            Annotation::DefaultValue(_) => state.write_i8(4),
225            Annotation::Index(_) => state.write_i8(5),
226            Annotation::MaxLength(_) => state.write_i8(6),
227            Annotation::NotNull => state.write_i8(7),
228            Annotation::PrimaryKey => state.write_i8(8),
229            Annotation::Unique => state.write_i8(9),
230            Annotation::ForeignKey(_) => state.write_i8(10),
231        }
232        state.finish()
233    }
234}
235
236#[cfg(test)]
237mod test {
238
239    use crate::imr::{Annotation, IndexValue};
240
241    #[test]
242    fn test_annotation_hash() {
243        assert_eq!(
244            Annotation::MaxLength(1).hash_shallow(),
245            Annotation::MaxLength(12313).hash_shallow()
246        );
247
248        assert_eq!(
249            Annotation::Index(None).hash_shallow(),
250            Annotation::Index(Some(IndexValue {
251                priority: None,
252                name: "foo".to_string(),
253            }))
254            .hash_shallow()
255        );
256    }
257
258    #[test]
259    fn test_annotation_partial_eq() {
260        assert!(Annotation::MaxLength(1).eq_shallow(&Annotation::MaxLength(2)));
261        assert!(
262            Annotation::Index(None).eq_shallow(&Annotation::Index(Some(IndexValue {
263                priority: None,
264                name: "foo".to_string()
265            })))
266        );
267    }
268}
269
270#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq, Default)]
272#[serde(rename_all = "PascalCase")]
273pub struct ForeignKey {
274    pub table_name: String,
276    pub column_name: String,
278    pub on_delete: ReferentialAction,
280    pub on_update: ReferentialAction,
282}
283
284#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
288#[serde(rename_all = "PascalCase")]
289pub enum ReferentialAction {
290    Restrict,
292    Cascade,
294    SetNull,
296    SetDefault,
298}
299
300impl Default for ReferentialAction {
301    fn default() -> Self {
302        Self::Restrict
303    }
304}
305
306impl Display for ReferentialAction {
307    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
308        match self {
309            ReferentialAction::Restrict => write!(f, "RESTRICT"),
310            ReferentialAction::Cascade => write!(f, "CASCADE"),
311            ReferentialAction::SetNull => write!(f, "SET NULL"),
312            ReferentialAction::SetDefault => write!(f, "SET DEFAULT"),
313        }
314    }
315}
316
317#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
319#[serde(rename_all = "PascalCase")]
320pub struct IndexValue {
321    pub name: String,
324
325    #[serde(default)]
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub priority: Option<i32>,
330}
331
332#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
334#[serde(untagged)]
335pub enum DefaultValue {
336    String(String),
338    Integer(i64),
340    Float(OrderedFloat<f64>),
342    Boolean(bool),
344}
345
346impl Default for DefaultValue {
350    fn default() -> Self {
351        DefaultValue::Boolean(true)
352    }
353}