Skip to main content

xsd_parser/traits/
naming.rs

1use std::any::Any;
2use std::fmt::{Debug, Display};
3use std::mem::take;
4
5use proc_macro2::Ident as Ident2;
6use quote::format_ident;
7
8use crate::models::{
9    meta::{MetaType, MetaTypes},
10    schema::NamespaceId,
11    Name, TypeIdent,
12};
13
14/// This trait defined how names are generated and formatted in `xsd-parser`.
15///
16/// Use the [`Interpreter::with_naming`](crate::Interpreter::with_naming) method
17/// to use a customized implementation for this trait.
18pub trait Naming: Debug {
19    /// Clone this object into a new `Box`.
20    fn clone_boxed(&self) -> Box<dyn Naming>;
21
22    /// Create a new name builder instance.
23    fn builder(&self) -> Box<dyn NameBuilder>;
24
25    /// Unify the given string.
26    ///
27    /// Before actual name generation or formatting it is sometimes useful
28    /// to have a pre-formatting for names, to have a unified schema for the
29    /// names in general.
30    ///
31    /// The default implementation uses pascal case to unify all different kind
32    /// of names.
33    fn unify(&self, s: &str) -> String;
34
35    /// Generate a name for the passed type `ty` identified by `ident` respecting the
36    /// configured type postfixes.
37    fn make_type_name(&self, postfixes: &[String], ty: &MetaType, ident: &TypeIdent) -> Name;
38
39    /// Create an unknown enum variant using the provided id.
40    ///
41    /// The default implementation generated `Unknown{id}` here.
42    fn make_unknown_variant(&self, id: usize) -> Ident2;
43
44    /// Format the passed string `s` as module name.
45    fn format_module_name(&self, s: &str) -> String;
46
47    /// Format the passed string `s` as type name.
48    fn format_type_name(&self, s: &str) -> String;
49
50    /// Format the passed string `s` as field name.
51    fn format_field_name(&self, s: &str) -> String;
52
53    /// Format the passed string `s` as variant name.
54    fn format_variant_name(&self, s: &str) -> String;
55
56    /// Format the passed string `s` as constant name.
57    fn format_constant_name(&self, s: &str) -> String;
58
59    /// Format the passed string `s` as attribute field name.
60    ///
61    /// The default implementation simply uses [`format_field_name`](Naming::format_field_name).
62    fn format_attribute_field_name(&self, s: &str) -> String {
63        self.format_field_name(s)
64    }
65
66    /// Format the passed string `s` as element field name.
67    ///
68    /// The default implementation simply uses [`format_field_name`](Naming::format_field_name).
69    fn format_element_field_name(&self, s: &str) -> String {
70        self.format_field_name(s)
71    }
72
73    /// Create a suitable identifier for the passed module name `name`.
74    ///
75    /// The default implementation uses [`format_module_ident`](Naming::format_module_ident)
76    /// with `display_name` set to `None` here.
77    fn format_module_ident(&self, name: &Name) -> Ident2 {
78        let ident = self.format_module_name(name.as_str());
79
80        format_ident!("{ident}")
81    }
82
83    /// Create a suitable identifier for the passed type name `name` respecting
84    /// user defined names stored in `display_name`.
85    ///
86    /// The default implementation uses the `display_name` or `name` as fallback
87    /// and formats it using [`format_type_name`](Naming::format_type_name).
88    fn format_type_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
89        let ident = self.format_type_name(display_name.unwrap_or(name.as_str()));
90
91        format_ident!("{ident}")
92    }
93
94    /// Create a suitable identifier for the passed field name `name` respecting
95    /// user defined names stored in `display_name`.
96    ///
97    /// The default implementation uses the `display_name` or `name` as fallback
98    /// and formats it using [`format_field_name`](Naming::format_field_name).
99    fn format_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
100        let ident = self.format_field_name(display_name.unwrap_or(name.as_str()));
101
102        format_ident!("{ident}")
103    }
104
105    /// Create a suitable identifier for the passed variant name `name` respecting
106    /// user defined names stored in `display_name`.
107    ///
108    /// The default implementation uses [`format_type_ident`](Naming::format_type_ident) here.
109    fn format_variant_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
110        let ident = self.format_variant_name(display_name.unwrap_or(name.as_str()));
111
112        format_ident!("{ident}")
113    }
114
115    /// Create a suitable identifier for the passed constant name `name` respecting
116    /// user defined names stored in `display_name`.
117    ///
118    /// The default implementation uses [`format_constant_name`](Naming::format_constant_name) here.
119    fn format_constant_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
120        let ident = self.format_constant_name(display_name.unwrap_or(name.as_str()));
121
122        format_ident!("{ident}")
123    }
124
125    /// Create a suitable identifier for the passed attribute field name `name`
126    /// respecting user defined names stored in `display_name`.
127    ///
128    /// The default implementation uses [`format_attribute_field_name`](Naming::format_attribute_field_name).
129    fn format_attribute_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
130        let ident = self.format_attribute_field_name(display_name.unwrap_or(name.as_str()));
131
132        format_ident!("{ident}")
133    }
134
135    /// Create a suitable identifier for the passed element field name `name`
136    /// respecting user defined names stored in `display_name`.
137    ///
138    /// The default implementation uses [`format_element_field_name`](Naming::format_element_field_name).
139    fn format_element_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
140        let ident = self.format_element_field_name(display_name.unwrap_or(name.as_str()));
141
142        format_ident!("{ident}")
143    }
144
145    /// Generate a identifier for the module identified by `ns`.
146    fn format_module(&self, types: &MetaTypes, ns: Option<NamespaceId>) -> Option<Ident2> {
147        let ns = ns?;
148        let module = types.modules.get(&ns)?;
149        let name = module.name.as_ref()?;
150
151        Some(self.format_module_ident(name))
152    }
153}
154
155/// This trait defines a builder for building type names.
156///
157/// The general idea of the builder is the following:
158/// - A type name needs a name to be valid. The name is set by
159///   [`set_name`](NameBuilder::set_name).
160/// - The name can be extended by multiple prefixes using
161///   [`add_extension`](NameBuilder::add_extension).
162/// - Sometimes is it not possible to create a unique name. To get one
163///   the builder should add a unique id to the name (this is controlled by
164///   [`set_with_id`](NameBuilder::set_with_id)).
165/// - The output of the name builder is a [`Name`]. `Name`s can be fixed or
166///   generated. The name builder should decide automatically which variant of
167///   the name has to be generated, if not explicitly specified by the user
168///   (using [`set_generated`](NameBuilder::set_generated)).
169pub trait NameBuilder: Debug + Any {
170    /// Finish the current name building and create a [`Name`] from the known
171    /// information.
172    fn finish(&self) -> Name;
173
174    /// Merge the data of the `other` name builder into the current name builder.
175    /// The passed name builder is of the same type then the current one.
176    fn merge(&mut self, other: &dyn NameBuilder);
177
178    /// Create a clone of the current builder and return it as box.
179    fn clone_boxed(&self) -> Box<dyn NameBuilder>;
180
181    /// Returns `true` if this builder has a name set, `false` otherwise.
182    fn has_name(&self) -> bool;
183
184    /// Returns `true` if this builder has at least on extension set, `false` otherwise.
185    fn has_extension(&self) -> bool;
186
187    /// Set the base name of this builder.
188    fn set_name(&mut self, name: String);
189
190    /// Instruct the builder to add a unique id to the generated name or not.
191    fn set_with_id(&mut self, value: bool);
192
193    /// Instruct the builder to generated a [`Name::Generated`] if `true` is passed,
194    /// or a [`Name::Named`] if `false` is passed.
195    fn set_generated(&mut self, value: bool);
196
197    /// Add a new `extension` to the builder. If `replace` is set to true, any previous
198    /// extension is dropped.
199    fn add_extension(&mut self, replace: bool, extension: String);
200
201    /// Remove the specified `suffix` from the name and the extensions.
202    fn strip_suffix(&mut self, suffix: &str);
203
204    /// Force the builder to generate a unique id, that is later used to generate
205    /// the name.
206    ///
207    /// Normally the id should be generated as last step (in the
208    /// [`finish`](NameBuilder::finish) method), but sometimes it is useful to
209    /// force the builder to generate the id to shared it between different copies
210    /// of the builder.
211    fn generate_unique_id(&mut self);
212
213    /// Prepare the builder to create a type name.
214    fn prepare_type_name(&mut self);
215
216    /// Prepare the builder to create a field name.
217    fn prepare_field_name(&mut self);
218
219    /// Prepare the builder to create a content type name.
220    fn prepare_content_type_name(&mut self);
221}
222
223impl NameBuilder for Box<dyn NameBuilder> {
224    #[inline]
225    fn finish(&self) -> Name {
226        (**self).finish()
227    }
228
229    #[inline]
230    fn merge(&mut self, other: &dyn NameBuilder) {
231        (**self).merge(other);
232    }
233
234    #[inline]
235    fn clone_boxed(&self) -> Box<dyn NameBuilder> {
236        (**self).clone_boxed()
237    }
238
239    #[inline]
240    fn has_name(&self) -> bool {
241        (**self).has_name()
242    }
243
244    #[inline]
245    fn has_extension(&self) -> bool {
246        (**self).has_extension()
247    }
248
249    #[inline]
250    fn set_name(&mut self, name: String) {
251        (**self).set_name(name);
252    }
253
254    #[inline]
255    fn set_with_id(&mut self, value: bool) {
256        (**self).set_with_id(value);
257    }
258
259    #[inline]
260    fn set_generated(&mut self, value: bool) {
261        (**self).set_generated(value);
262    }
263
264    #[inline]
265    fn add_extension(&mut self, replace: bool, extension: String) {
266        (**self).add_extension(replace, extension);
267    }
268
269    #[inline]
270    fn strip_suffix(&mut self, suffix: &str) {
271        (**self).strip_suffix(suffix);
272    }
273
274    #[inline]
275    fn generate_unique_id(&mut self) {
276        (**self).generate_unique_id();
277    }
278
279    #[inline]
280    fn prepare_type_name(&mut self) {
281        (**self).prepare_type_name();
282    }
283
284    #[inline]
285    fn prepare_field_name(&mut self) {
286        (**self).prepare_field_name();
287    }
288
289    #[inline]
290    fn prepare_content_type_name(&mut self) {
291        (**self).prepare_content_type_name();
292    }
293}
294
295/// Helper trait that provides additional builder patterns to the [`NameBuilder`].
296pub trait NameBuilderExt: Sized {
297    /// Force the builder to generate a unique id.
298    #[must_use]
299    fn generate_id(self) -> Self;
300
301    /// Tell the builder to add (`true`) or not to add (`false`) the unique id
302    /// to the generated name.
303    #[must_use]
304    fn with_id(self, value: bool) -> Self;
305
306    /// Add extensions to the builder using the passed iterator `iter`. If `replace`
307    /// is set to `true` any existing extension is dropped before the new ones are
308    /// applied.
309    #[must_use]
310    fn extend<I>(self, replace: bool, iter: I) -> Self
311    where
312        I: IntoIterator,
313        I::Item: Display;
314
315    /// Remove the specified `suffix` from the builder.
316    #[must_use]
317    fn remove_suffix(self, suffix: &str) -> Self;
318
319    /// Instruct the builder to create a unique name from the passed `value`.
320    ///
321    /// This means, that the [`with_id`](NameBuilderExt::with_id) is automatically
322    /// set to `false`.
323    #[must_use]
324    fn unique_name<T>(self, value: T) -> Self
325    where
326        T: Display;
327
328    /// Instruct the builder to create a name that is shared between different parts
329    /// of the code from the passed `value`.
330    ///
331    /// This means, that the [`with_id`](NameBuilderExt::with_id) is automatically
332    /// set to `true` and the generated name has a unique id to be identified.
333    #[must_use]
334    fn shared_name<T>(self, value: T) -> Self
335    where
336        T: Display;
337
338    /// If the builder does currently not have a name, the passed `fallback` is applied.
339    #[must_use]
340    fn or<T>(self, fallback: T) -> Self
341    where
342        T: NameFallback;
343
344    /// If the builder does currently not have a name, the passed `fallback` is applied.
345    #[must_use]
346    fn or_else<F, T>(self, fallback: F) -> Self
347    where
348        F: FnOnce() -> T,
349        T: NameFallback;
350
351    /// Prepare the builder to create a type name.
352    #[must_use]
353    fn type_name(self) -> Self;
354
355    /// Prepare the builder to create a field name.
356    #[must_use]
357    fn field_name(self) -> Self;
358
359    /// Prepare the builder to create a content type name.
360    #[must_use]
361    fn content_type_name(self) -> Self;
362}
363
364impl<X> NameBuilderExt for X
365where
366    X: NameBuilder + Sized,
367{
368    fn generate_id(mut self) -> Self {
369        self.generate_unique_id();
370
371        self
372    }
373
374    fn with_id(mut self, value: bool) -> Self {
375        self.set_with_id(value);
376
377        self
378    }
379
380    fn extend<I>(mut self, mut replace: bool, iter: I) -> Self
381    where
382        I: IntoIterator,
383        I::Item: Display,
384    {
385        for ext in iter {
386            let ext = ext.to_string();
387
388            self.add_extension(take(&mut replace), ext);
389        }
390
391        self
392    }
393
394    fn remove_suffix(mut self, suffix: &str) -> Self {
395        self.strip_suffix(suffix);
396
397        self
398    }
399
400    fn unique_name<T>(mut self, value: T) -> Self
401    where
402        T: Display,
403    {
404        self.set_name(value.to_string());
405        self.set_with_id(false);
406
407        self
408    }
409
410    fn shared_name<T>(mut self, value: T) -> Self
411    where
412        T: Display,
413    {
414        self.set_name(value.to_string());
415        self.set_with_id(true);
416
417        self
418    }
419
420    fn or<T>(self, fallback: T) -> Self
421    where
422        T: NameFallback,
423    {
424        self.or_else(|| fallback)
425    }
426
427    fn or_else<F, T>(mut self, fallback: F) -> Self
428    where
429        F: FnOnce() -> T,
430        T: NameFallback,
431    {
432        if !self.has_name() {
433            fallback().apply(&mut self);
434        }
435
436        self
437    }
438
439    fn type_name(mut self) -> Self {
440        self.prepare_type_name();
441
442        self
443    }
444
445    fn field_name(mut self) -> Self {
446        self.prepare_field_name();
447
448        self
449    }
450
451    fn content_type_name(mut self) -> Self {
452        self.prepare_content_type_name();
453
454        self
455    }
456}
457
458/// Helper trait used in [`NameBuilderExt::or`] and [`NameBuilderExt::or_else`] to define
459/// what can be used as fallback for a name.
460pub trait NameFallback {
461    /// Apply the fallback to the passed `builder`.
462    fn apply(self, builder: &mut dyn NameBuilder);
463}
464
465impl NameFallback for &dyn NameBuilder {
466    fn apply(self, builder: &mut dyn NameBuilder) {
467        builder.merge(self);
468    }
469}
470
471impl NameFallback for Box<dyn NameBuilder> {
472    fn apply(self, builder: &mut dyn NameBuilder) {
473        builder.merge(&*self);
474    }
475}
476
477impl NameFallback for Name {
478    #[inline]
479    fn apply(self, builder: &mut dyn NameBuilder) {
480        (&self).apply(builder);
481    }
482}
483
484impl NameFallback for &Name {
485    #[inline]
486    fn apply(self, builder: &mut dyn NameBuilder) {
487        builder.set_name(self.as_str().to_owned());
488        builder.set_generated(self.is_generated());
489        builder.set_with_id(false);
490    }
491}
492
493impl NameFallback for Option<&Name> {
494    #[inline]
495    fn apply(self, builder: &mut dyn NameBuilder) {
496        if let Some(x) = self {
497            x.apply(builder);
498        }
499    }
500}
501
502impl NameFallback for Option<Name> {
503    #[inline]
504    fn apply(self, builder: &mut dyn NameBuilder) {
505        self.as_ref().apply(builder);
506    }
507}
508
509impl NameFallback for &Option<Name> {
510    fn apply(self, builder: &mut dyn NameBuilder) {
511        self.as_ref().apply(builder);
512    }
513}
514
515impl NameFallback for &String {
516    fn apply(self, builder: &mut dyn NameBuilder) {
517        builder.set_name(self.to_owned());
518        builder.set_with_id(false);
519    }
520}
521
522impl NameFallback for Option<&String> {
523    fn apply(self, builder: &mut dyn NameBuilder) {
524        if let Some(x) = self {
525            x.apply(builder);
526        }
527    }
528}
529
530impl NameFallback for Option<String> {
531    fn apply(self, builder: &mut dyn NameBuilder) {
532        self.as_ref().apply(builder);
533    }
534}
535
536impl NameFallback for &Option<String> {
537    fn apply(self, builder: &mut dyn NameBuilder) {
538        self.as_ref().apply(builder);
539    }
540}
541
542impl NameFallback for &str {
543    fn apply(self, builder: &mut dyn NameBuilder) {
544        builder.set_name(self.to_owned());
545        builder.set_with_id(false);
546    }
547}
548
549impl NameFallback for Option<&str> {
550    fn apply(self, builder: &mut dyn NameBuilder) {
551        if let Some(x) = self {
552            x.apply(builder);
553        }
554    }
555}