Skip to main content

openapi_model_generator/
models.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub enum ModelType {
5    Struct(Model),
6    Union(UnionModel),             // oneOf/anyOf -> enum
7    Composition(CompositionModel), // allOf
8    Enum(EnumModel),               // enum values -> enum
9    TypeAlias(TypeAliasModel),     // x-rust-type -> type alias
10}
11
12impl ModelType {
13    pub fn name(&self) -> &str {
14        match self {
15            ModelType::Struct(m) => &m.name,
16            ModelType::Enum(e) => &e.name,
17            ModelType::Union(u) => &u.name,
18            ModelType::Composition(c) => &c.name,
19            ModelType::TypeAlias(t) => &t.name,
20        }
21    }
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct Model {
26    pub name: String,
27    pub fields: Vec<Field>,
28    pub custom_attrs: Option<Vec<String>>,
29    pub description: Option<String>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct Field {
34    pub name: String,
35    pub field_type: String,
36    pub format: String,
37    pub is_required: bool,
38    pub is_nullable: bool,
39    pub is_array_ref: bool,
40    pub description: Option<String>,
41    /// Field-level Rust attributes from x-rust-attrs (e.g. #[serde(rename = "...")])
42    #[serde(default)]
43    pub custom_attrs: Option<Vec<String>>,
44    /// Validation rules extracted from OpenAPI specification
45    #[serde(default)]
46    pub validation_rules: Option<ValidationRules>,
47}
48
49impl Field {
50    /// Returns true if this field should be flattened (for additionalProperties)
51    pub fn should_flatten(&self) -> bool {
52        self.name == "additional_properties"
53    }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct UnionModel {
58    pub name: String,
59    pub variants: Vec<UnionVariant>,
60    pub union_type: UnionType,
61    pub custom_attrs: Option<Vec<String>>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub enum UnionType {
66    OneOf,
67    AnyOf,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct UnionVariant {
72    pub name: String,
73    pub fields: Vec<Field>,
74    pub primitive_type: Option<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct CompositionModel {
79    pub name: String,
80    pub all_fields: Vec<Field>,
81    pub custom_attrs: Option<Vec<String>>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct RequestModel {
86    pub name: String,
87    pub content_type: String,
88    pub schema: String,
89    pub is_required: bool,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct ResponseModel {
94    pub name: String,
95    pub status_code: String,
96    pub content_type: String,
97    pub schema: String,
98    pub description: Option<String>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct EnumModel {
103    pub name: String,
104    pub variants: Vec<String>,
105    pub description: Option<String>,
106    pub custom_attrs: Option<Vec<String>>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct TypeAliasModel {
111    pub name: String,
112    pub target_type: String,
113    pub description: Option<String>,
114    pub custom_attrs: Option<Vec<String>>,
115}
116
117/// Validation rules extracted from OpenAPI specification
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
119pub struct ValidationRules {
120    // String validation
121    pub min_length: Option<usize>,
122    pub max_length: Option<usize>,
123    pub pattern: Option<String>,
124    pub email: bool,
125    pub url: bool,
126
127    // Number validation (stored as f64 to handle both Integer and Number types)
128    pub minimum: Option<f64>,
129    pub maximum: Option<f64>,
130    pub exclusive_minimum: bool,
131    pub exclusive_maximum: bool,
132    pub multiple_of: Option<f64>,
133
134    // Array validation
135    pub min_items: Option<usize>,
136    pub max_items: Option<usize>,
137    pub unique_items: bool,
138}
139
140impl ValidationRules {
141    /// Returns true if there are any validation rules defined
142    pub fn has_any(&self) -> bool {
143        self.min_length.is_some()
144            || self.max_length.is_some()
145            || self.pattern.is_some()
146            || self.email
147            || self.url
148            || self.minimum.is_some()
149            || self.maximum.is_some()
150            || self.exclusive_minimum
151            || self.exclusive_maximum
152            || self.multiple_of.is_some()
153            || self.min_items.is_some()
154            || self.max_items.is_some()
155            || self.unique_items
156    }
157}