xsd_parser/models/naming/
mod.rs1mod default;
2mod explicit;
3
4use std::borrow::Cow;
5
6use inflector::Inflector;
7use proc_macro2::Ident as Ident2;
8use quote::format_ident;
9
10use crate::config::MetaType;
11use crate::models::meta::MetaTypeVariant;
12use crate::models::schema::MaxOccurs;
13use crate::TypeIdent;
14
15use super::Name;
16
17pub use self::default::{NameBuilder, Naming};
18pub use self::explicit::{ExplicitNameBuilder, ExplicitNaming};
19
20pub fn make_type_name<X>(naming: &X, postfixes: &[String], ty: &MetaType, ident: &TypeIdent) -> Name
22where
23 X: crate::traits::Naming,
24{
25 if let MetaTypeVariant::Reference(ti) = &ty.variant {
26 if ident.name.is_generated() && ti.type_.name.is_named() {
27 let s = naming.format_type_name(ti.type_.name.as_str());
28
29 if ti.max_occurs > MaxOccurs::Bounded(1) {
30 return Name::new_generated(format!("{s}List"));
31 } else if ti.min_occurs == 0 {
32 return Name::new_generated(format!("{s}Opt"));
33 }
34 }
35 }
36
37 let postfix = postfixes
38 .get(ident.type_ as usize)
39 .map_or("", |s| s.as_str());
40
41 let s = naming.format_type_name(ident.name.as_str());
42
43 if s.ends_with(postfix) {
44 ident.name.clone()
45 } else {
46 Name::new_generated(format!("{s}{postfix}"))
47 }
48}
49
50#[must_use]
52pub fn unify_string(s: &str) -> String {
53 let mut done = true;
54 let s = s.replace(
55 |c: char| {
56 let replace = !c.is_alphanumeric();
57 if c != '_' && !replace {
58 done = false;
59 }
60
61 c != '_' && replace
62 },
63 "_",
64 );
65
66 if done {
67 s
68 } else {
69 s.to_screaming_snake_case().to_pascal_case()
70 }
71}
72
73#[must_use]
75pub fn format_unknown_variant(id: usize) -> Ident2 {
76 format_ident!("Unknown{id}")
77}
78
79#[must_use]
82pub fn format_ident<'a, S>(s: S) -> String
83where
84 S: Into<Cow<'a, str>>,
85{
86 let mut s = s.into();
87 if let Ok(idx) = KEYWORDS.binary_search_by(|(key, _)| key.cmp(&&*s)) {
88 s = Cow::Borrowed(KEYWORDS[idx].1);
89 }
90
91 if s.starts_with(char::is_numeric) {
92 s = Cow::Owned(format!("_{s}"));
93 }
94
95 s.replace(|c: char| !c.is_alphanumeric(), "_")
96}
97
98const KEYWORDS: &[(&str, &str)] = &[
101 ("Self", "Self_"),
102 ("abstract", "abstract_"),
103 ("as", "as_"),
104 ("become", "become_"),
105 ("box", "box_"),
106 ("break", "break_"),
107 ("const", "const_"),
108 ("continue", "continue_"),
109 ("crate", "crate_"),
110 ("do", "do_"),
111 ("else", "else_"),
112 ("enum", "enum_"),
113 ("extern", "extern_"),
114 ("false", "false_"),
115 ("final", "final_"),
116 ("fn", "fn_"),
117 ("for", "for_"),
118 ("if", "if_"),
119 ("impl", "impl_"),
120 ("in", "in_"),
121 ("let", "let_"),
122 ("loop", "loop_"),
123 ("macro", "macro_"),
124 ("match", "match_"),
125 ("mod", "mod_"),
126 ("move", "move_"),
127 ("mut", "mut_"),
128 ("override", "override_"),
129 ("priv", "priv_"),
130 ("pub", "pub_"),
131 ("ref", "ref_"),
132 ("return", "return_"),
133 ("self", "self_"),
134 ("static", "static_"),
135 ("struct", "struct_"),
136 ("super", "super_"),
137 ("trait", "trait_"),
138 ("true", "true_"),
139 ("try", "try_"),
140 ("type", "type_"),
141 ("typeof", "typeof_"),
142 ("union", "union_"),
143 ("unsafe", "unsafe_"),
144 ("unsized", "unsized_"),
145 ("use", "use_"),
146 ("virtual", "virtual_"),
147 ("where", "where_"),
148 ("while", "while_"),
149 ("yield", "yield_"),
150];
151
152#[cfg(test)]
153mod tests {
154 use super::KEYWORDS;
155
156 #[test]
157 fn verify_keyword_order() {
158 for i in 1..KEYWORDS.len() {
159 assert!(dbg!(KEYWORDS[i - 1].0) < dbg!(KEYWORDS[i].0));
160 }
161 }
162}