use clarax_core::types::{FieldDescriptor as CoreDescriptor, FieldType as CoreFieldType};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldDescriptor {
pub name: String,
pub field_type: DjangoFieldType,
pub nullable: bool,
pub has_default: bool,
}
impl FieldDescriptor {
pub fn to_core(&self) -> CoreDescriptor {
CoreDescriptor {
name: self.name.clone(),
field_type: self.field_type.to_core_type(),
nullable: self.nullable,
has_default: self.has_default,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DjangoFieldType {
CharField { max_length: usize },
TextField,
IntegerField,
BigIntegerField,
FloatField,
DecimalField { max_digits: u32, decimal_places: u32 },
BooleanField,
DateField,
TimeField,
DateTimeField,
UuidField,
JsonField,
BinaryField { max_length: Option<usize> },
EmailField { max_length: usize },
UrlField { max_length: usize },
SlugField { max_length: usize },
}
impl DjangoFieldType {
pub fn django_type_name(&self) -> &'static str {
match self {
DjangoFieldType::CharField { .. } => "CharField",
DjangoFieldType::TextField => "TextField",
DjangoFieldType::IntegerField => "IntegerField",
DjangoFieldType::BigIntegerField => "BigIntegerField",
DjangoFieldType::FloatField => "FloatField",
DjangoFieldType::DecimalField { .. } => "DecimalField",
DjangoFieldType::BooleanField => "BooleanField",
DjangoFieldType::DateField => "DateField",
DjangoFieldType::TimeField => "TimeField",
DjangoFieldType::DateTimeField => "DateTimeField",
DjangoFieldType::UuidField => "UUIDField",
DjangoFieldType::JsonField => "JSONField",
DjangoFieldType::BinaryField { .. } => "BinaryField",
DjangoFieldType::EmailField { .. } => "EmailField",
DjangoFieldType::UrlField { .. } => "URLField",
DjangoFieldType::SlugField { .. } => "SlugField",
}
}
pub fn to_core_type(&self) -> CoreFieldType {
match self {
DjangoFieldType::CharField { max_length } => CoreFieldType::Str {
max_length: Some(*max_length),
min_length: None,
},
DjangoFieldType::TextField => CoreFieldType::Str {
max_length: None,
min_length: None,
},
DjangoFieldType::IntegerField => CoreFieldType::Int {
min_value: Some(i32::MIN as i64),
max_value: Some(i32::MAX as i64),
},
DjangoFieldType::BigIntegerField => CoreFieldType::Int {
min_value: None,
max_value: None,
},
DjangoFieldType::FloatField => CoreFieldType::Float {
min_value: None,
max_value: None,
},
DjangoFieldType::DecimalField { max_digits, decimal_places } => CoreFieldType::Decimal {
max_digits: Some(*max_digits),
decimal_places: Some(*decimal_places),
},
DjangoFieldType::BooleanField => CoreFieldType::Bool,
DjangoFieldType::DateField => CoreFieldType::Date,
DjangoFieldType::TimeField => CoreFieldType::Time,
DjangoFieldType::DateTimeField => CoreFieldType::DateTime,
DjangoFieldType::UuidField => CoreFieldType::Uuid,
DjangoFieldType::JsonField => CoreFieldType::Dict,
DjangoFieldType::BinaryField { max_length } => CoreFieldType::Bytes {
max_length: *max_length,
},
DjangoFieldType::EmailField { max_length } => CoreFieldType::Str {
max_length: Some(*max_length),
min_length: None,
},
DjangoFieldType::UrlField { max_length } => CoreFieldType::Str {
max_length: Some(*max_length),
min_length: None,
},
DjangoFieldType::SlugField { max_length } => CoreFieldType::Str {
max_length: Some(*max_length),
min_length: None,
},
}
}
}
pub use clarax_core::types::FieldValue;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn field_descriptor_converts_to_core() {
let desc = FieldDescriptor {
name: "price".into(),
field_type: DjangoFieldType::DecimalField {
max_digits: 10,
decimal_places: 2,
},
nullable: false,
has_default: false,
};
let core = desc.to_core();
assert_eq!(core.name, "price");
assert!(matches!(core.field_type, CoreFieldType::Decimal { .. }));
}
#[test]
fn django_type_names_round_trip() {
assert_eq!(DjangoFieldType::CharField { max_length: 100 }.django_type_name(), "CharField");
assert_eq!(DjangoFieldType::UuidField.django_type_name(), "UUIDField");
assert_eq!(DjangoFieldType::JsonField.django_type_name(), "JSONField");
}
#[test]
fn charfield_maps_to_str_with_max_length() {
let ct = DjangoFieldType::CharField { max_length: 50 }.to_core_type();
match ct {
CoreFieldType::Str { max_length, .. } => assert_eq!(max_length, Some(50)),
_ => panic!("expected Str"),
}
}
}