xsd_parser/types/
name_builder.rs1use std::fmt::Display;
2use std::mem::take;
3use std::sync::atomic::Ordering;
4use std::sync::{atomic::AtomicUsize, Arc};
5
6use super::Name;
7
8#[must_use]
10#[derive(Debug, Clone)]
11pub struct NameBuilder {
12 id: Arc<AtomicUsize>,
13 my_id: Option<usize>,
14 with_id: bool,
15 generated: bool,
16
17 name: Option<String>,
18 extension: Option<String>,
19}
20
21impl NameBuilder {
22 pub fn new(id: Arc<AtomicUsize>) -> Self {
26 Self {
27 id,
28 my_id: None,
29 with_id: true,
30 generated: false,
31 name: None,
32 extension: None,
33 }
34 }
35
36 #[must_use]
38 pub fn finish(self) -> Name {
39 let Self {
40 id,
41 my_id,
42 with_id,
43 mut generated,
44 name,
45 extension,
46 } = self;
47
48 let mut ret = String::new();
49 if let Some(s) = extension {
50 generated = true;
51 ret.push_str(&Name::unify(&s));
52 }
53
54 if let Some(s) = name {
55 if ret.is_empty() {
56 ret.push_str(&s);
57 } else {
58 ret.push_str(&Name::unify(&s));
59 }
60 }
61
62 if ret.is_empty() {
63 generated = true;
64 ret.push_str("Unnamed");
65 }
66
67 if with_id {
68 generated = true;
69 let id = my_id.unwrap_or_else(|| id.fetch_add(1, Ordering::Relaxed));
70 ret = format!("{ret}{id}");
71 }
72
73 if generated {
74 Name::new_generated(ret)
75 } else {
76 Name::new_named(ret)
77 }
78 }
79
80 pub fn with_id(mut self, value: bool) -> Self {
82 self.with_id = value;
83
84 self
85 }
86
87 pub fn generate_id(mut self) -> Self {
92 if self.my_id.is_none() {
93 self.my_id = Some(self.id.fetch_add(1, Ordering::Release));
94 }
95
96 self
97 }
98
99 pub fn unique_name<T>(mut self, value: T) -> Self
103 where
104 T: Display,
105 {
106 self.name = Some(value.to_string());
107 self.with_id = false;
108
109 self
110 }
111
112 pub fn shared_name<T>(mut self, value: T) -> Self
116 where
117 T: Display,
118 {
119 self.name = Some(value.to_string());
120 self.with_id = true;
121
122 self
123 }
124
125 pub fn or<T>(self, fallback: T) -> Self
128 where
129 T: NameFallback,
130 {
131 self.or_else(|| fallback)
132 }
133
134 pub fn or_else<F, T>(mut self, fallback: F) -> Self
137 where
138 F: FnOnce() -> T,
139 T: NameFallback,
140 {
141 if self.name.is_none() {
142 if let Some((generated, name)) = fallback().resolve() {
143 self.name = Some(name);
144 self.with_id = false;
145 self.generated = generated;
146 }
147 }
148
149 self
150 }
151
152 pub fn extend<I>(mut self, mut replace: bool, iter: I) -> Self
156 where
157 I: IntoIterator,
158 I::Item: Display,
159 {
160 for s in iter {
161 let s = s.to_string();
162 let s = Name::unify(&s);
163
164 if take(&mut replace) {
165 self.extension = Some(s);
166 } else if let Some(prefix) = &self.extension {
167 self.extension = Some(format!("{s}{prefix}"));
168 } else {
169 self.extension = Some(s);
170 }
171 }
172
173 self
174 }
175
176 pub fn remove_suffix(mut self, suffix: &str) -> Self {
178 if let Some(s) = &mut self.name {
179 if let Some(x) = s.strip_suffix(suffix) {
180 *s = x.into();
181 }
182 }
183
184 if let Some(s) = &mut self.extension {
185 if let Some(x) = s.strip_suffix(suffix) {
186 *s = x.into();
187 }
188 }
189
190 self
191 }
192
193 #[inline]
195 #[must_use]
196 pub fn has_extension(&self) -> bool {
197 self.extension.is_some()
198 }
199}
200
201pub trait NameFallback {
204 fn resolve(self) -> Option<(bool, String)>;
206}
207
208impl NameFallback for Name {
209 #[inline]
210 fn resolve(self) -> Option<(bool, String)> {
211 (&self).resolve()
212 }
213}
214
215impl NameFallback for &Name {
216 #[inline]
217 fn resolve(self) -> Option<(bool, String)> {
218 Some((self.is_generated(), self.as_str().to_owned()))
219 }
220}
221
222impl NameFallback for Option<&Name> {
223 #[inline]
224 fn resolve(self) -> Option<(bool, String)> {
225 self.and_then(NameFallback::resolve)
226 }
227}
228
229impl NameFallback for Option<Name> {
230 #[inline]
231 fn resolve(self) -> Option<(bool, String)> {
232 self.as_ref().resolve()
233 }
234}
235
236impl NameFallback for &Option<Name> {
237 fn resolve(self) -> Option<(bool, String)> {
238 self.as_ref().resolve()
239 }
240}
241
242impl NameFallback for &String {
243 fn resolve(self) -> Option<(bool, String)> {
244 Some((false, self.to_owned()))
245 }
246}
247
248impl NameFallback for Option<&String> {
249 fn resolve(self) -> Option<(bool, String)> {
250 self.and_then(NameFallback::resolve)
251 }
252}
253
254impl NameFallback for Option<String> {
255 fn resolve(self) -> Option<(bool, String)> {
256 self.as_ref().resolve()
257 }
258}
259
260impl NameFallback for &Option<String> {
261 fn resolve(self) -> Option<(bool, String)> {
262 self.as_ref().resolve()
263 }
264}
265
266impl NameFallback for &str {
267 fn resolve(self) -> Option<(bool, String)> {
268 Some((false, self.to_owned()))
269 }
270}
271
272impl NameFallback for Option<&str> {
273 fn resolve(self) -> Option<(bool, String)> {
274 self.and_then(NameFallback::resolve)
275 }
276}