Skip to main content

unistructgen_openapi_parser/
options.rs

1//! Parser configuration options
2
3use std::collections::HashSet;
4
5/// Options for configuring the OpenAPI parser
6#[derive(Debug, Clone)]
7pub struct OpenApiParserOptions {
8    /// Generate API client traits
9    pub generate_client: bool,
10
11    /// Generate validation derives and attributes
12    pub generate_validation: bool,
13
14    /// Add serde derives to generated structs
15    pub derive_serde: bool,
16
17    /// Add Default derive to generated structs
18    pub derive_default: bool,
19
20    /// Make all fields optional (wrap in Option<T>)
21    pub make_fields_optional: bool,
22
23    /// Maximum depth for nested schemas (prevents infinite recursion)
24    pub max_depth: usize,
25
26    /// Tag names to filter (only include these tags)
27    pub include_tags: Option<HashSet<String>>,
28
29    /// Tag names to exclude
30    pub exclude_tags: Option<HashSet<String>>,
31
32    /// Generate builder pattern for request types
33    pub generate_builders: bool,
34
35    /// Add documentation comments from OpenAPI descriptions
36    pub generate_docs: bool,
37
38    /// Prefix for generated type names
39    pub type_prefix: Option<String>,
40
41    /// Suffix for generated type names
42    pub type_suffix: Option<String>,
43
44    /// Module name for generated code
45    pub module_name: String,
46}
47
48impl Default for OpenApiParserOptions {
49    fn default() -> Self {
50        Self {
51            generate_client: true,
52            generate_validation: true,
53            derive_serde: true,
54            derive_default: false,
55            make_fields_optional: false,
56            max_depth: 10,
57            include_tags: None,
58            exclude_tags: None,
59            generate_builders: false,
60            generate_docs: true,
61            type_prefix: None,
62            type_suffix: None,
63            module_name: "api".to_string(),
64        }
65    }
66}
67
68impl OpenApiParserOptions {
69    /// Create a new builder for parser options
70    pub fn builder() -> OpenApiParserOptionsBuilder {
71        OpenApiParserOptionsBuilder::default()
72    }
73
74    /// Check if a tag should be included
75    pub fn should_include_tag(&self, tag: &str) -> bool {
76        // If include_tags is specified, only include those
77        if let Some(ref include) = self.include_tags {
78            if !include.contains(tag) {
79                return false;
80            }
81        }
82
83        // Check exclude list
84        if let Some(ref exclude) = self.exclude_tags {
85            if exclude.contains(tag) {
86                return false;
87            }
88        }
89
90        true
91    }
92
93    /// Apply prefix and suffix to type name
94    pub fn format_type_name(&self, name: &str) -> String {
95        let mut result = String::new();
96
97        if let Some(ref prefix) = self.type_prefix {
98            result.push_str(prefix);
99        }
100
101        result.push_str(name);
102
103        if let Some(ref suffix) = self.type_suffix {
104            result.push_str(suffix);
105        }
106
107        result
108    }
109}
110
111/// Builder for OpenApiParserOptions
112#[derive(Debug, Default)]
113pub struct OpenApiParserOptionsBuilder {
114    generate_client: Option<bool>,
115    generate_validation: Option<bool>,
116    derive_serde: Option<bool>,
117    derive_default: Option<bool>,
118    make_fields_optional: Option<bool>,
119    max_depth: Option<usize>,
120    include_tags: Option<HashSet<String>>,
121    exclude_tags: Option<HashSet<String>>,
122    generate_builders: Option<bool>,
123    generate_docs: Option<bool>,
124    type_prefix: Option<String>,
125    type_suffix: Option<String>,
126    module_name: Option<String>,
127}
128
129impl OpenApiParserOptionsBuilder {
130    /// Create a new builder
131    pub fn new() -> Self {
132        Self::default()
133    }
134
135    /// Set whether to generate API client traits
136    pub fn generate_client(mut self, value: bool) -> Self {
137        self.generate_client = Some(value);
138        self
139    }
140
141    /// Set whether to generate validation
142    pub fn generate_validation(mut self, value: bool) -> Self {
143        self.generate_validation = Some(value);
144        self
145    }
146
147    /// Set whether to derive serde traits
148    pub fn derive_serde(mut self, value: bool) -> Self {
149        self.derive_serde = Some(value);
150        self
151    }
152
153    /// Set whether to derive Default trait
154    pub fn derive_default(mut self, value: bool) -> Self {
155        self.derive_default = Some(value);
156        self
157    }
158
159    /// Set whether to make all fields optional
160    pub fn make_fields_optional(mut self, value: bool) -> Self {
161        self.make_fields_optional = Some(value);
162        self
163    }
164
165    /// Set maximum depth for nested schemas
166    pub fn max_depth(mut self, value: usize) -> Self {
167        self.max_depth = Some(value);
168        self
169    }
170
171    /// Set tags to include
172    pub fn include_tags(mut self, tags: HashSet<String>) -> Self {
173        self.include_tags = Some(tags);
174        self
175    }
176
177    /// Set tags to exclude
178    pub fn exclude_tags(mut self, tags: HashSet<String>) -> Self {
179        self.exclude_tags = Some(tags);
180        self
181    }
182
183    /// Set whether to generate builder patterns
184    pub fn generate_builders(mut self, value: bool) -> Self {
185        self.generate_builders = Some(value);
186        self
187    }
188
189    /// Set whether to generate documentation
190    pub fn generate_docs(mut self, value: bool) -> Self {
191        self.generate_docs = Some(value);
192        self
193    }
194
195    /// Set type name prefix
196    pub fn type_prefix(mut self, prefix: impl Into<String>) -> Self {
197        self.type_prefix = Some(prefix.into());
198        self
199    }
200
201    /// Set type name suffix
202    pub fn type_suffix(mut self, suffix: impl Into<String>) -> Self {
203        self.type_suffix = Some(suffix.into());
204        self
205    }
206
207    /// Set module name
208    pub fn module_name(mut self, name: impl Into<String>) -> Self {
209        self.module_name = Some(name.into());
210        self
211    }
212
213    /// Build the options
214    pub fn build(self) -> OpenApiParserOptions {
215        let defaults = OpenApiParserOptions::default();
216
217        OpenApiParserOptions {
218            generate_client: self.generate_client.unwrap_or(defaults.generate_client),
219            generate_validation: self
220                .generate_validation
221                .unwrap_or(defaults.generate_validation),
222            derive_serde: self.derive_serde.unwrap_or(defaults.derive_serde),
223            derive_default: self.derive_default.unwrap_or(defaults.derive_default),
224            make_fields_optional: self
225                .make_fields_optional
226                .unwrap_or(defaults.make_fields_optional),
227            max_depth: self.max_depth.unwrap_or(defaults.max_depth),
228            include_tags: self.include_tags.or(defaults.include_tags),
229            exclude_tags: self.exclude_tags.or(defaults.exclude_tags),
230            generate_builders: self.generate_builders.unwrap_or(defaults.generate_builders),
231            generate_docs: self.generate_docs.unwrap_or(defaults.generate_docs),
232            type_prefix: self.type_prefix.or(defaults.type_prefix),
233            type_suffix: self.type_suffix.or(defaults.type_suffix),
234            module_name: self.module_name.unwrap_or(defaults.module_name),
235        }
236    }
237}