Skip to main content

xsd_parser/models/naming/
default.rs

1use std::any::Any;
2use std::sync::{
3    atomic::{AtomicUsize, Ordering},
4    Arc,
5};
6
7use inflector::Inflector;
8use proc_macro2::Ident as Ident2;
9
10use crate::models::{meta::MetaType, TypeIdent};
11use crate::traits::{NameBuilder as NameBuilderTrait, Naming as NamingTrait};
12
13use super::Name;
14
15/// Default name generation and formatting implementation.
16///
17/// This type implements the [`Naming`](NamingTrait) trait that is used for
18/// naming generation and formatting.
19#[derive(Default, Debug, Clone)]
20pub struct Naming(Arc<AtomicUsize>);
21
22impl NamingTrait for Naming {
23    fn clone_boxed(&self) -> Box<dyn NamingTrait> {
24        Box::new(self.clone())
25    }
26
27    fn builder(&self) -> Box<dyn NameBuilderTrait> {
28        Box::new(NameBuilder::new(self.0.clone(), Box::new(self.clone())))
29    }
30
31    fn unify(&self, s: &str) -> String {
32        super::unify_string(s)
33    }
34
35    fn make_type_name(&self, postfixes: &[String], ty: &MetaType, ident: &TypeIdent) -> Name {
36        super::make_type_name(self, postfixes, ty, ident)
37    }
38
39    fn make_unknown_variant(&self, id: usize) -> Ident2 {
40        super::format_unknown_variant(id)
41    }
42
43    fn format_module_name(&self, s: &str) -> String {
44        let s = self.unify(s).to_snake_case();
45
46        super::format_ident(s)
47    }
48
49    fn format_type_name(&self, s: &str) -> String {
50        let s = self.unify(s);
51
52        super::format_ident(s)
53    }
54
55    fn format_field_name(&self, s: &str) -> String {
56        let s = self.unify(s).to_snake_case();
57
58        super::format_ident(s)
59    }
60
61    fn format_variant_name(&self, s: &str) -> String {
62        let s = self.unify(s);
63
64        super::format_ident(s)
65    }
66
67    fn format_constant_name(&self, s: &str) -> String {
68        let s = self.unify(s).to_screaming_snake_case();
69
70        super::format_ident(s)
71    }
72}
73
74/// Default implementation for the [`NameBuilder`](NameBuilderTrait) trait.
75#[must_use]
76#[derive(Debug)]
77pub struct NameBuilder {
78    id: Arc<AtomicUsize>,
79    my_id: Option<usize>,
80    with_id: bool,
81    generated: bool,
82
83    name: Option<String>,
84    extension: Option<String>,
85
86    naming: Box<dyn NamingTrait>,
87}
88
89impl NameBuilder {
90    /// Create a new [`NameBuilder`] instance.
91    ///
92    /// The passed `id` is used to generate unique ids for unnamed types.
93    pub fn new(id: Arc<AtomicUsize>, naming: Box<dyn NamingTrait>) -> Self {
94        Self {
95            id,
96            my_id: None,
97            with_id: true,
98            generated: false,
99            name: None,
100            extension: None,
101            naming,
102        }
103    }
104}
105
106impl Clone for NameBuilder {
107    fn clone(&self) -> Self {
108        Self {
109            id: self.id.clone(),
110            my_id: self.my_id,
111            with_id: self.with_id,
112            generated: self.generated,
113            name: self.name.clone(),
114            extension: self.extension.clone(),
115            naming: self.naming.clone_boxed(),
116        }
117    }
118}
119
120impl NameBuilderTrait for NameBuilder {
121    fn finish(&self) -> Name {
122        let Self {
123            id,
124            my_id,
125            with_id,
126            mut generated,
127            name,
128            extension,
129            naming,
130        } = self;
131
132        let mut ret = String::new();
133        if let Some(s) = extension {
134            generated = true;
135            ret.push_str(&naming.unify(s));
136        }
137
138        if let Some(s) = name {
139            if ret.is_empty() {
140                ret.push_str(s);
141            } else {
142                ret.push_str(&naming.unify(s));
143            }
144        }
145
146        if ret.is_empty() {
147            generated = true;
148            ret.push_str("Unnamed");
149        }
150
151        if *with_id {
152            generated = true;
153            let id = my_id.unwrap_or_else(|| id.fetch_add(1, Ordering::Relaxed));
154            ret = format!("{ret}{id}");
155        }
156
157        if generated {
158            Name::new_generated(ret)
159        } else {
160            Name::new_named(ret)
161        }
162    }
163
164    fn merge(&mut self, other: &dyn NameBuilderTrait) {
165        let other: &Self = (other as &dyn Any).downcast_ref().unwrap();
166
167        if let Some(name) = other.name.clone() {
168            self.name.get_or_insert(name);
169            self.with_id = other.with_id;
170            self.generated = other.generated;
171
172            if let Some(id) = other.my_id {
173                self.with_id = other.with_id;
174                self.my_id.get_or_insert(id);
175            }
176
177            if let Some(ext) = other.extension.clone() {
178                self.extension.get_or_insert(ext);
179            }
180        }
181    }
182
183    fn clone_boxed(&self) -> Box<dyn NameBuilderTrait> {
184        Box::new(self.clone())
185    }
186
187    fn has_name(&self) -> bool {
188        self.name.is_some()
189    }
190
191    fn has_extension(&self) -> bool {
192        self.extension.is_some()
193    }
194
195    fn set_name(&mut self, name: String) {
196        self.name = Some(name);
197    }
198
199    fn set_with_id(&mut self, value: bool) {
200        self.with_id = value;
201    }
202
203    fn set_generated(&mut self, value: bool) {
204        self.generated = value;
205    }
206
207    fn add_extension(&mut self, replace: bool, extension: String) {
208        let s = self.naming.unify(&extension);
209
210        if replace {
211            self.extension = Some(s);
212        } else if let Some(prefix) = &self.extension {
213            self.extension = Some(format!("{s}{prefix}"));
214        } else {
215            self.extension = Some(s);
216        }
217    }
218
219    fn strip_suffix(&mut self, suffix: &str) {
220        if let Some(s) = &mut self.name {
221            if let Some(x) = s.strip_suffix(suffix) {
222                *s = x.into();
223            }
224        }
225
226        if let Some(s) = &mut self.extension {
227            if let Some(x) = s.strip_suffix(suffix) {
228                *s = x.into();
229            }
230        }
231    }
232
233    fn generate_unique_id(&mut self) {
234        if self.my_id.is_none() {
235            self.my_id = Some(self.id.fetch_add(1, Ordering::Release));
236        }
237    }
238
239    fn prepare_type_name(&mut self) {
240        self.strip_suffix("Type");
241        self.strip_suffix("Content");
242    }
243
244    fn prepare_field_name(&mut self) {
245        self.strip_suffix("Type");
246        self.strip_suffix("Content");
247    }
248
249    fn prepare_content_type_name(&mut self) {
250        self.strip_suffix("Type");
251        self.strip_suffix("Content");
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use crate::traits::Naming as _;
258
259    use super::Naming;
260
261    #[test]
262    fn default_naming() {
263        let naming = Naming::default();
264
265        assert_eq!("_", naming.unify("+"));
266        assert_eq!("FuuBarBaz", naming.unify("Fuu_BAR_BAZ"));
267        assert_eq!("FuuBarBaz", naming.unify("fuu_bar_baz"));
268        assert_eq!("FuuBarBaz", naming.unify("fuu+Bar-BAZ"));
269
270        assert_eq!("QName", naming.unify("QName"));
271        assert_eq!("QName", naming.format_type_name("QName"));
272        assert_eq!("QName", naming.format_variant_name("QName"));
273        assert_eq!("q_name", naming.format_field_name("QName"));
274    }
275}