Skip to main content

unistructgen_core/
ir.rs

1use serde::{Deserialize, Serialize};
2
3/// Intermediate Representation Module
4/// Contains all types that will be generated
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct IRModule {
7    pub name: String,
8    pub types: Vec<IRType>,
9}
10
11/// Type definition in the IR
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub enum IRType {
14    Struct(IRStruct),
15    Enum(IREnum),
16}
17
18/// Struct definition
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct IRStruct {
21    pub name: String,
22    pub fields: Vec<IRField>,
23    pub derives: Vec<String>,
24    pub doc: Option<String>,
25    pub attributes: Vec<String>,
26}
27
28/// Enum definition
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct IREnum {
31    pub name: String,
32    pub variants: Vec<IREnumVariant>,
33    pub derives: Vec<String>,
34    pub doc: Option<String>,
35}
36
37/// Enum variant
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct IREnumVariant {
40    pub name: String,
41    /// Original value from the source (e.g., "open" vs "Open")
42    pub source_value: Option<String>,
43    pub doc: Option<String>,
44}
45
46/// Field in a struct
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct IRField {
49    pub name: String,
50    /// Original name in the source (e.g., JSON key)
51    pub source_name: Option<String>,
52    pub ty: IRTypeRef,
53    pub optional: bool,
54    pub default: Option<String>,
55    pub constraints: FieldConstraints,
56    pub attributes: Vec<String>,
57    pub doc: Option<String>,
58}
59
60/// Type reference
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
62pub enum IRTypeRef {
63    /// Primitive types (String, i32, f64, bool, etc.)
64    Primitive(PrimitiveKind),
65    /// Option<T>
66    Option(Box<IRTypeRef>),
67    /// Vec<T>
68    Vec(Box<IRTypeRef>),
69    /// Named type (struct/enum reference)
70    Named(String),
71    /// Map/HashMap<K, V>
72    Map(Box<IRTypeRef>, Box<IRTypeRef>),
73}
74
75/// Primitive type kinds
76#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
77pub enum PrimitiveKind {
78    String,
79    I8,
80    I16,
81    I32,
82    I64,
83    I128,
84    U8,
85    U16,
86    U32,
87    U64,
88    U128,
89    F32,
90    F64,
91    Bool,
92    Char,
93    // Special types
94    DateTime,
95    Uuid,
96    Decimal,
97    Json,
98}
99
100impl PrimitiveKind {
101    pub fn rust_type_name(&self) -> &'static str {
102        match self {
103            PrimitiveKind::String => "String",
104            PrimitiveKind::I8 => "i8",
105            PrimitiveKind::I16 => "i16",
106            PrimitiveKind::I32 => "i32",
107            PrimitiveKind::I64 => "i64",
108            PrimitiveKind::I128 => "i128",
109            PrimitiveKind::U8 => "u8",
110            PrimitiveKind::U16 => "u16",
111            PrimitiveKind::U32 => "u32",
112            PrimitiveKind::U64 => "u64",
113            PrimitiveKind::U128 => "u128",
114            PrimitiveKind::F32 => "f32",
115            PrimitiveKind::F64 => "f64",
116            PrimitiveKind::Bool => "bool",
117            PrimitiveKind::Char => "char",
118            PrimitiveKind::DateTime => "chrono::DateTime<chrono::Utc>",
119            PrimitiveKind::Uuid => "uuid::Uuid",
120            PrimitiveKind::Decimal => "rust_decimal::Decimal",
121            PrimitiveKind::Json => "serde_json::Value",
122        }
123    }
124}
125
126/// Field constraints for validation
127#[derive(Debug, Clone, Serialize, Deserialize, Default)]
128pub struct FieldConstraints {
129    pub min_length: Option<usize>,
130    pub max_length: Option<usize>,
131    pub min_value: Option<f64>,
132    pub max_value: Option<f64>,
133    pub pattern: Option<String>,
134    pub format: Option<String>,
135}
136
137impl IRModule {
138    pub fn new(name: String) -> Self {
139        Self {
140            name,
141            types: Vec::new(),
142        }
143    }
144
145    pub fn add_type(&mut self, ty: IRType) {
146        self.types.push(ty);
147    }
148}
149
150impl IRStruct {
151    pub fn new(name: String) -> Self {
152        Self {
153            name,
154            fields: Vec::new(),
155            derives: vec![
156                "Debug".to_string(),
157                "Clone".to_string(),
158                "PartialEq".to_string(),
159            ],
160            doc: None,
161            attributes: Vec::new(),
162        }
163    }
164
165    pub fn add_field(&mut self, field: IRField) {
166        self.fields.push(field);
167    }
168
169    pub fn add_derive(&mut self, derive: String) {
170        if !self.derives.contains(&derive) {
171            self.derives.push(derive);
172        }
173    }
174}
175
176impl IRField {
177    pub fn new(name: String, ty: IRTypeRef) -> Self {
178        Self {
179            name,
180            source_name: None,
181            ty,
182            optional: false,
183            default: None,
184            constraints: FieldConstraints::default(),
185            attributes: Vec::new(),
186            doc: None,
187        }
188    }
189}
190
191impl IRTypeRef {
192    pub fn is_primitive(&self) -> bool {
193        matches!(self, IRTypeRef::Primitive(_))
194    }
195
196    pub fn is_optional(&self) -> bool {
197        matches!(self, IRTypeRef::Option(_))
198    }
199
200    pub fn make_optional(self) -> Self {
201        match self {
202            IRTypeRef::Option(_) => self,
203            other => IRTypeRef::Option(Box::new(other)),
204        }
205    }
206}