use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use ordered_float::OrderedFloat;
use serde::Deserialize;
use serde::Serialize;
#[derive(Serialize, Deserialize, Debug, Clone, Hash)]
#[serde(rename_all = "PascalCase")]
pub struct InternalModelFormat {
pub models: Vec<Model>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct Model {
pub name: String,
pub fields: Vec<Field>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub source_defined_at: Option<Source>,
}
impl PartialEq for Model {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.fields == other.fields
}
}
impl Hash for Model {
fn hash<H: Hasher>(&self, state: &mut H) {
self.fields.hash(state);
self.name.hash(state);
}
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where
Self: Sized,
{
data.iter().for_each(|x| x.hash(state));
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct Field {
pub name: String,
#[serde(rename = "Type")]
pub db_type: DbType,
pub annotations: Vec<Annotation>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub source_defined_at: Option<Source>,
}
impl PartialEq for Field {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.db_type == other.db_type
&& self.annotations == other.annotations
}
}
impl Hash for Field {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.annotations.hash(state);
self.db_type.hash(state);
}
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where
Self: Sized,
{
data.iter().for_each(|x| x.hash(state));
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash)]
#[serde(rename_all = "PascalCase")]
pub struct Source {
pub file: String,
pub line: usize,
pub column: usize,
}
#[allow(missing_docs)]
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum DbType {
VarChar,
Binary,
Int8,
Int16,
Int32,
Int64,
#[serde(rename = "float_number")]
Float,
#[serde(rename = "double_number")]
Double,
Boolean,
Date,
DateTime,
Timestamp,
Time,
Choices,
Uuid,
MacAddress,
IpNetwork,
BitVec,
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(tag = "Type", content = "Value")]
#[serde(rename_all = "snake_case")]
pub enum Annotation {
AutoCreateTime,
AutoUpdateTime,
AutoIncrement,
Choices(Vec<String>),
DefaultValue(DefaultValue),
Index(Option<IndexValue>),
MaxLength(i32),
NotNull,
PrimaryKey,
Unique,
ForeignKey(ForeignKey),
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq, Default)]
#[serde(rename_all = "PascalCase")]
pub struct ForeignKey {
pub table_name: String,
pub column_name: String,
pub on_delete: ReferentialAction,
pub on_update: ReferentialAction,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub enum ReferentialAction {
Restrict,
Cascade,
SetNull,
SetDefault,
}
impl Default for ReferentialAction {
fn default() -> Self {
Self::Restrict
}
}
impl Display for ReferentialAction {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ReferentialAction::Restrict => write!(f, "RESTRICT"),
ReferentialAction::Cascade => write!(f, "CASCADE"),
ReferentialAction::SetNull => write!(f, "SET NULL"),
ReferentialAction::SetDefault => write!(f, "SET DEFAULT"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub struct IndexValue {
pub name: String,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<i32>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
#[serde(untagged)]
pub enum DefaultValue {
String(String),
Integer(i64),
Float(OrderedFloat<f64>),
Boolean(bool),
}