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
16 name: Option<String>,
17 extension: Option<String>,
18}
19
20impl NameBuilder {
21 pub fn new(id: Arc<AtomicUsize>) -> Self {
25 Self {
26 id,
27 my_id: None,
28 with_id: true,
29 name: None,
30 extension: None,
31 }
32 }
33
34 #[must_use]
36 pub fn finish(self) -> Name {
37 let Self {
38 id,
39 my_id,
40 with_id,
41 name,
42 extension,
43 } = self;
44
45 let mut generated = false;
46
47 let mut ret = String::new();
48 if let Some(s) = extension {
49 generated = true;
50 ret.push_str(&Name::unify(&s));
51 }
52
53 if let Some(s) = name {
54 ret.push_str(&s);
55 }
56
57 if ret.is_empty() {
58 generated = true;
59 ret.push_str("Unnamed");
60 }
61
62 if with_id {
63 generated = true;
64 let id = my_id.unwrap_or_else(|| id.fetch_add(1, Ordering::Relaxed));
65 ret = format!("{ret}{id}");
66 }
67
68 if generated {
69 Name::new_generated(ret)
70 } else {
71 Name::new_named(ret)
72 }
73 }
74
75 pub fn with_id(mut self, value: bool) -> Self {
77 self.with_id = value;
78
79 self
80 }
81
82 pub fn generate_id(mut self) -> Self {
87 if self.my_id.is_none() {
88 self.my_id = Some(self.id.fetch_add(1, Ordering::Release));
89 }
90
91 self
92 }
93
94 pub fn unique_name<T>(mut self, value: T) -> Self
98 where
99 T: Display,
100 {
101 self.name = Some(value.to_string());
102 self.with_id = false;
103
104 self
105 }
106
107 pub fn shared_name<T>(mut self, value: T) -> Self
111 where
112 T: Display,
113 {
114 self.name = Some(value.to_string());
115 self.with_id = true;
116
117 self
118 }
119
120 pub fn or<T>(self, fallback: T) -> Self
123 where
124 T: NameFallback,
125 {
126 self.or_else(|| fallback)
127 }
128
129 pub fn or_else<F, T>(mut self, fallback: F) -> Self
132 where
133 F: FnOnce() -> T,
134 T: NameFallback,
135 {
136 self.name = self.name.or_else(|| fallback().resolve());
137 if self.name.is_some() {
138 self.with_id = false;
139 }
140
141 self
142 }
143
144 pub fn extend<I>(mut self, mut replace: bool, iter: I) -> Self
148 where
149 I: IntoIterator,
150 I::Item: Display,
151 {
152 for s in iter {
153 let s = s.to_string();
154 let s = Name::unify(&s);
155
156 if take(&mut replace) {
157 self.extension = Some(s);
158 } else if let Some(prefix) = &self.extension {
159 self.extension = Some(format!("{s}{prefix}"));
160 } else {
161 self.extension = Some(s);
162 }
163 }
164
165 self
166 }
167
168 pub fn remove_suffix(mut self, suffix: &str) -> Self {
170 if let Some(s) = &mut self.name {
171 if let Some(x) = s.strip_suffix(suffix) {
172 *s = x.into();
173 }
174 }
175
176 if let Some(s) = &mut self.extension {
177 if let Some(x) = s.strip_suffix(suffix) {
178 *s = x.into();
179 }
180 }
181
182 self
183 }
184
185 #[inline]
187 #[must_use]
188 pub fn has_extension(&self) -> bool {
189 self.extension.is_some()
190 }
191}
192
193pub trait NameFallback {
196 fn resolve(self) -> Option<String>;
198}
199
200impl NameFallback for Name {
201 fn resolve(self) -> Option<String> {
202 Some(self.as_str().to_owned())
203 }
204}
205
206impl NameFallback for &String {
207 fn resolve(self) -> Option<String> {
208 Some(self.to_owned())
209 }
210}
211
212impl NameFallback for &Name {
213 fn resolve(self) -> Option<String> {
214 Some(self.as_str().to_owned())
215 }
216}
217
218impl<X> NameFallback for Option<X>
219where
220 X: Display,
221{
222 fn resolve(self) -> Option<String> {
223 self.map(|x| format!("{x}"))
224 }
225}
226
227impl<X> NameFallback for &Option<X>
228where
229 X: Display,
230{
231 fn resolve(self) -> Option<String> {
232 self.as_ref().map(|x| format!("{x}"))
233 }
234}