1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct IRModule {
7 pub name: String,
8 pub types: Vec<IRType>,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub enum IRType {
14 Struct(IRStruct),
15 Enum(IREnum),
16}
17
18#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct IREnumVariant {
40 pub name: String,
41 pub source_value: Option<String>,
43 pub doc: Option<String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct IRField {
49 pub name: String,
50 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#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
62pub enum IRTypeRef {
63 Primitive(PrimitiveKind),
65 Option(Box<IRTypeRef>),
67 Vec(Box<IRTypeRef>),
69 Named(String),
71 Map(Box<IRTypeRef>, Box<IRTypeRef>),
73}
74
75#[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 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#[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}