Skip to main content

rh_codegen/
rust_types.rs

1//! Rust-specific types and structures for code generation
2//!
3//! This module contains data structures that represent generated Rust code elements
4//! such as structs, fields, enums, and their associated metadata.
5
6/// Represents a generated Rust struct
7#[derive(Debug, Clone)]
8pub struct RustStruct {
9    pub name: String,
10    pub doc_comment: Option<String>,
11    pub fields: Vec<RustField>,
12    pub derives: Vec<String>,
13    pub is_public: bool,
14    pub base_definition: Option<String>,
15}
16
17impl RustStruct {
18    pub fn new(name: String) -> Self {
19        Self {
20            name,
21            doc_comment: None,
22            fields: Vec::new(),
23            derives: vec![
24                "Debug".to_string(),
25                "Clone".to_string(),
26                "Deserialize".to_string(),
27                "Serialize".to_string(),
28            ],
29            is_public: true,
30            base_definition: None,
31        }
32    }
33
34    pub fn with_doc(mut self, doc: String) -> Self {
35        self.doc_comment = Some(doc);
36        self
37    }
38
39    pub fn add_field(&mut self, field: RustField) {
40        self.fields.push(field);
41    }
42}
43
44/// Represents a field in a Rust struct
45#[derive(Debug, Clone)]
46pub struct RustField {
47    pub name: String,
48    pub field_type: RustType,
49    pub doc_comment: Option<String>,
50    pub is_optional: bool,
51    pub is_public: bool,
52    pub serde_attributes: Vec<String>,
53    /// If set, this field should be rendered as a macro call instead of a regular field
54    pub macro_call: Option<String>,
55}
56
57impl RustField {
58    pub fn new(name: String, field_type: RustType) -> Self {
59        Self {
60            name,
61            field_type,
62            doc_comment: None,
63            is_optional: false,
64            is_public: true,
65            serde_attributes: Vec::new(),
66            macro_call: None,
67        }
68    }
69
70    /// Create a new field that represents a macro call
71    pub fn new_macro_call(macro_call: String) -> Self {
72        // Extract field name from macro call for display purposes
73        let field_name = Self::extract_field_name_from_macro_call(&macro_call);
74
75        Self {
76            name: field_name,
77            field_type: RustType::Custom("MacroCall".to_string()), // Placeholder type
78            doc_comment: None,
79            is_optional: false,
80            is_public: true,
81            serde_attributes: Vec::new(),
82            macro_call: Some(macro_call),
83        }
84    }
85
86    /// Extract field name from a macro call string
87    fn extract_field_name_from_macro_call(macro_call: &str) -> String {
88        // Parse macro call like: primitive_string!("field_name", true)
89        if let Some(start) = macro_call.find('(') {
90            if let Some(end) = macro_call.find(',') {
91                let content = &macro_call[start + 1..end];
92                let field_name = content.trim().trim_matches('"');
93                return field_name.to_string();
94            }
95        }
96        "unknown_field".to_string()
97    }
98
99    pub fn optional(mut self) -> Self {
100        self.is_optional = true;
101        self
102    }
103
104    pub fn with_doc(mut self, doc: String) -> Self {
105        self.doc_comment = Some(doc);
106        self
107    }
108
109    pub fn with_serde_rename(mut self, name: String) -> Self {
110        self.serde_attributes.push(format!("rename = \"{name}\""));
111        self
112    }
113}
114
115/// Represents a Rust type
116#[derive(Debug, Clone)]
117pub enum RustType {
118    String,
119    Integer,
120    Boolean,
121    Float,
122    Option(Box<RustType>),
123    Vec(Box<RustType>),
124    Box(Box<RustType>),
125    Slice(Box<RustType>),
126    Custom(String),
127    Reference(String),
128}
129
130impl RustType {
131    #[allow(clippy::inherent_to_string)]
132    pub fn to_string(&self) -> String {
133        match self {
134            RustType::String => "String".to_string(),
135            RustType::Integer => "i32".to_string(),
136            RustType::Boolean => "bool".to_string(),
137            RustType::Float => "f64".to_string(),
138            RustType::Option(inner) => format!("Option<{}>", inner.to_string()),
139            RustType::Vec(inner) => format!("Vec<{}>", inner.to_string()),
140            RustType::Box(inner) => format!("Box<{}>", inner.to_string()),
141            RustType::Slice(inner) => format!("[{}]", inner.to_string()),
142            RustType::Custom(name) => name.clone(),
143            RustType::Reference(name) => format!("&{name}"),
144        }
145    }
146
147    pub fn wrap_in_option(self) -> Self {
148        match self {
149            RustType::Option(_) => self,
150            _ => RustType::Option(Box::new(self)),
151        }
152    }
153}
154
155/// Represents a generated Rust enum
156#[derive(Debug, Clone)]
157pub struct RustEnum {
158    pub name: String,
159    pub doc_comment: Option<String>,
160    pub variants: Vec<RustEnumVariant>,
161    pub derives: Vec<String>,
162    pub is_public: bool,
163}
164
165impl RustEnum {
166    pub fn new(name: String) -> Self {
167        Self {
168            name,
169            doc_comment: None,
170            variants: Vec::new(),
171            derives: vec!["Debug".to_string(), "Clone".to_string()],
172            is_public: true,
173        }
174    }
175
176    pub fn add_variant(&mut self, variant: RustEnumVariant) {
177        self.variants.push(variant);
178    }
179}
180
181/// Represents a variant in a Rust enum
182#[derive(Debug, Clone)]
183pub struct RustEnumVariant {
184    pub name: String,
185    pub doc_comment: Option<String>,
186    pub data: Option<RustType>,
187    pub serde_rename: Option<String>,
188}
189
190impl RustEnumVariant {
191    pub fn new(name: String) -> Self {
192        Self {
193            name,
194            doc_comment: None,
195            data: None,
196            serde_rename: None,
197        }
198    }
199
200    pub fn with_data(mut self, data: RustType) -> Self {
201        self.data = Some(data);
202        self
203    }
204
205    pub fn with_serde_rename(mut self, rename: String) -> Self {
206        self.serde_rename = Some(rename);
207        self
208    }
209}
210
211/// Represents a Rust type alias
212#[derive(Debug, Clone)]
213pub struct RustTypeAlias {
214    pub name: String,
215    pub target_type: RustType,
216    pub doc_comment: Option<String>,
217    pub is_public: bool,
218}
219
220impl RustTypeAlias {
221    pub fn new(name: String, target_type: RustType) -> Self {
222        Self {
223            name,
224            target_type,
225            doc_comment: None,
226            is_public: true,
227        }
228    }
229
230    pub fn with_doc(mut self, doc: String) -> Self {
231        self.doc_comment = Some(doc);
232        self
233    }
234}
235
236/// Represents a generated code module
237#[derive(Debug, Clone)]
238pub struct RustModule {
239    pub name: String,
240    pub structs: Vec<RustStruct>,
241    pub enums: Vec<RustEnum>,
242    pub imports: Vec<String>,
243    pub doc_comment: Option<String>,
244}
245
246impl RustModule {
247    pub fn new(name: String) -> Self {
248        Self {
249            name,
250            structs: Vec::new(),
251            enums: Vec::new(),
252            imports: vec!["serde::{Deserialize, Serialize}".to_string()],
253            doc_comment: None,
254        }
255    }
256
257    pub fn add_struct(&mut self, rust_struct: RustStruct) {
258        self.structs.push(rust_struct);
259    }
260
261    pub fn add_enum(&mut self, rust_enum: RustEnum) {
262        self.enums.push(rust_enum);
263    }
264
265    pub fn add_import(&mut self, import: String) {
266        if !self.imports.contains(&import) {
267            self.imports.push(import);
268        }
269    }
270}
271
272/// Represents a parameter in a Rust method
273#[derive(Debug, Clone)]
274pub struct RustMethodParam {
275    pub name: String,
276    pub param_type: RustType,
277    pub is_mut: bool,
278    pub is_ref: bool,
279}
280
281impl RustMethodParam {
282    pub fn new(name: String, param_type: RustType) -> Self {
283        Self {
284            name,
285            param_type,
286            is_mut: false,
287            is_ref: false,
288        }
289    }
290
291    pub fn with_mut(mut self) -> Self {
292        self.is_mut = true;
293        self
294    }
295
296    pub fn with_ref(mut self) -> Self {
297        self.is_ref = true;
298        self
299    }
300}
301
302/// Represents a Rust trait definition
303#[derive(Debug, Clone)]
304pub struct RustTrait {
305    pub name: String,
306    pub doc_comment: Option<String>,
307    pub methods: Vec<RustTraitMethod>,
308    pub is_public: bool,
309    pub super_traits: Vec<String>,
310}
311
312impl RustTrait {
313    pub fn new(name: String) -> Self {
314        Self {
315            name,
316            doc_comment: None,
317            methods: Vec::new(),
318            is_public: true,
319            super_traits: Vec::new(),
320        }
321    }
322
323    pub fn with_doc(mut self, doc: String) -> Self {
324        self.doc_comment = Some(doc);
325        self
326    }
327
328    pub fn add_method(&mut self, method: RustTraitMethod) {
329        // Check if a method with this name already exists
330        if !self
331            .methods
332            .iter()
333            .any(|existing| existing.name == method.name)
334        {
335            self.methods.push(method);
336        }
337    }
338
339    pub fn with_super_trait(mut self, super_trait: String) -> Self {
340        self.super_traits.push(super_trait);
341        self
342    }
343}
344
345/// Represents a method declaration in a trait
346#[derive(Debug, Clone)]
347pub struct RustTraitMethod {
348    pub name: String,
349    pub params: Vec<RustMethodParam>,
350    pub return_type: Option<RustType>,
351    pub doc_comment: Option<String>,
352    pub is_default: bool,
353    pub default_body: Option<String>,
354    /// The self parameter type: None (no self), Some("&self"), Some("&mut self"), Some("self")
355    pub self_param: Option<String>,
356}
357
358impl RustTraitMethod {
359    pub fn new(name: String) -> Self {
360        Self {
361            name,
362            params: Vec::new(),
363            return_type: None,
364            doc_comment: None,
365            is_default: false,
366            default_body: None,
367            self_param: Some("&self".to_string()), // Default to &self for backward compatibility
368        }
369    }
370
371    pub fn with_param(mut self, param: RustMethodParam) -> Self {
372        self.params.push(param);
373        self
374    }
375
376    pub fn with_parameter(mut self, name: String, param_type: RustType) -> Self {
377        self.params.push(RustMethodParam::new(name, param_type));
378        self
379    }
380
381    pub fn with_return_type(mut self, return_type: RustType) -> Self {
382        self.return_type = Some(return_type);
383        self
384    }
385
386    pub fn with_doc(mut self, doc: String) -> Self {
387        self.doc_comment = Some(doc);
388        self
389    }
390
391    pub fn with_default_implementation(mut self, body: String) -> Self {
392        self.is_default = true;
393        self.default_body = Some(body);
394        self
395    }
396
397    pub fn with_body(mut self, body: String) -> Self {
398        self.default_body = Some(body);
399        self
400    }
401
402    pub fn with_self_param(mut self, self_param: Option<String>) -> Self {
403        self.self_param = self_param;
404        self
405    }
406}
407
408/// Represents a Rust trait implementation
409#[derive(Debug, Clone)]
410pub struct RustTraitImpl {
411    /// The name of the trait being implemented
412    pub trait_name: String,
413    /// The name of the struct implementing the trait  
414    pub struct_name: String,
415    /// The methods implemented in this trait impl
416    pub methods: Vec<RustTraitImplMethod>,
417    /// Documentation comment for the impl
418    pub doc_comment: Option<String>,
419}
420
421impl RustTraitImpl {
422    pub fn new(trait_name: String, struct_name: String) -> Self {
423        Self {
424            trait_name,
425            struct_name,
426            methods: Vec::new(),
427            doc_comment: None,
428        }
429    }
430
431    pub fn with_doc(mut self, doc: String) -> Self {
432        self.doc_comment = Some(doc);
433        self
434    }
435
436    pub fn add_method(&mut self, method: RustTraitImplMethod) {
437        self.methods.push(method);
438    }
439
440    pub fn with_method(mut self, method: RustTraitImplMethod) -> Self {
441        self.methods.push(method);
442        self
443    }
444
445    /// Returns true if this trait implementation has no methods
446    pub fn is_empty(&self) -> bool {
447        self.methods.is_empty()
448    }
449}
450
451/// Represents a method implementation in a trait impl block
452#[derive(Debug, Clone)]
453pub struct RustTraitImplMethod {
454    /// The name of the method
455    pub name: String,
456    /// The parameters of the method (excluding self)
457    pub params: Vec<RustMethodParam>,
458    /// The return type of the method
459    pub return_type: String,
460    /// The body of the method implementation
461    pub body: String,
462    /// Documentation comment for the method
463    pub doc_comment: Option<String>,
464    /// The self parameter type: None (no self), Some("&self"), Some("&mut self"), Some("self")
465    pub self_param: Option<String>,
466}
467
468impl RustTraitImplMethod {
469    pub fn new(name: String) -> Self {
470        Self {
471            name,
472            params: Vec::new(),
473            return_type: "()".to_string(),
474            body: "todo!()".to_string(),
475            doc_comment: None,
476            self_param: Some("&self".to_string()), // Default to &self for backward compatibility
477        }
478    }
479
480    pub fn with_return_type(mut self, return_type: String) -> Self {
481        self.return_type = return_type;
482        self
483    }
484
485    pub fn with_body(mut self, body: String) -> Self {
486        self.body = body;
487        self
488    }
489
490    pub fn with_doc(mut self, doc: String) -> Self {
491        self.doc_comment = Some(doc);
492        self
493    }
494
495    pub fn add_param(&mut self, param: RustMethodParam) {
496        self.params.push(param);
497    }
498
499    pub fn with_param(mut self, param: RustMethodParam) -> Self {
500        self.params.push(param);
501        self
502    }
503
504    pub fn with_self_param(mut self, self_param: Option<String>) -> Self {
505        self.self_param = self_param;
506        self
507    }
508}