1use crate::{context, path, Merge};
2use indexmap::{
3 map::{self, Entry::*},
4 IndexMap,
5};
6use std::{
7 borrow::{
8 Borrow,
9 Cow::{self, *},
10 },
11 cmp::Ordering,
12 fmt::{Debug, Display, Formatter, Result},
13 hash::{Hash, Hasher},
14 mem::replace,
15};
16
17#[derive(Clone, Eq)]
18struct Key<'a>(Cow<'a, str>);
19
20impl PartialEq for Key<'_> {
21 #[inline]
22 fn eq(&self, other: &Self) -> bool {
23 self.0.eq_ignore_ascii_case(&other.0)
24 }
25}
26
27impl Ord for Key<'_> {
28 fn cmp(&self, other: &Self) -> Ordering {
29 let mut order = self.0.len().cmp(&other.0.len());
30
31 if order != Ordering::Equal {
32 return order;
33 }
34
35 for (a, b) in self.0.chars().zip(other.0.chars()) {
36 order = a.to_ascii_uppercase().cmp(&b.to_ascii_uppercase());
37
38 if order != Ordering::Equal {
39 break;
40 }
41 }
42
43 order
44 }
45}
46
47impl PartialOrd for Key<'_> {
48 #[inline]
49 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
50 Some(self.cmp(other))
51 }
52}
53
54impl Hash for Key<'_> {
55 fn hash<H: Hasher>(&self, state: &mut H) {
56 self.0
57 .as_ref()
58 .chars()
59 .map(|c| c.to_ascii_uppercase())
60 .for_each(|c| c.hash(state))
61 }
62}
63
64impl AsRef<str> for Key<'_> {
65 #[inline]
66 fn as_ref(&self) -> &str {
67 self.0.as_ref()
68 }
69}
70
71impl From<String> for Key<'static> {
72 #[inline]
73 fn from(value: String) -> Self {
74 Key(Owned(value))
75 }
76}
77
78impl<'a> From<&'a str> for Key<'a> {
79 #[inline]
80 fn from(value: &'a str) -> Self {
81 Key(Borrowed(value))
82 }
83}
84
85#[derive(Eq)]
89#[repr(transparent)]
90struct KeyRef(str);
91
92impl KeyRef {
93 #[inline]
94 fn new(s: &str) -> &Self {
95 unsafe { &*(s as *const str as *const KeyRef) }
98 }
99}
100
101impl PartialEq for KeyRef {
102 #[inline]
103 fn eq(&self, other: &Self) -> bool {
104 self.0.eq_ignore_ascii_case(&other.0)
105 }
106}
107
108impl Hash for KeyRef {
109 fn hash<H: Hasher>(&self, state: &mut H) {
110 self.0
111 .chars()
112 .map(|c| c.to_ascii_uppercase())
113 .for_each(|c| c.hash(state))
114 }
115}
116
117impl Borrow<KeyRef> for Key<'_> {
118 #[inline]
119 fn borrow(&self) -> &KeyRef {
120 KeyRef::new(self.0.as_ref())
121 }
122}
123
124impl Debug for Key<'_> {
125 #[inline]
126 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
127 Debug::fmt(&self.0, f)
128 }
129}
130
131impl Display for Key<'_> {
132 #[inline]
133 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
134 Display::fmt(&self.0, f)
135 }
136}
137
138#[derive(Clone, Default)]
140pub struct Settings(IndexMap<Key<'static>, (String, u8)>);
141
142impl Settings {
143 #[inline]
145 pub fn new() -> Self {
146 Self::default()
147 }
148
149 #[inline]
151 pub fn len(&self) -> usize {
152 self.0.len()
153 }
154
155 #[inline]
157 pub fn is_empty(&self) -> bool {
158 self.0.is_empty()
159 }
160
161 #[inline]
163 pub fn keys(&self) -> Keys<'_> {
164 Keys(self.0.keys())
165 }
166
167 pub(crate) fn get_subkey(&self, path: &str, key: &str) -> Option<&str> {
168 const CH_256: usize = 256;
169 let delimiter = path::delimiter();
170 let len = path.len() + 1 + key.len();
171
172 if len <= CH_256 {
173 let mut buf = [0u8; CH_256];
174
175 buf[..path.len()].copy_from_slice(path.as_bytes());
176 buf[path.len()] = delimiter as u8;
177 buf[path.len() + 1..len].copy_from_slice(key.as_bytes());
178
179 let combined = unsafe { std::str::from_utf8_unchecked(&buf[..len]) };
183 self.0.get(KeyRef::new(combined)).map(|(s, _)| s.as_str())
184 } else {
185 let combined = format!("{path}{delimiter}{key}");
186 self.0.get(KeyRef::new(combined.as_str())).map(|(s, _)| s.as_str())
187 }
188 }
189
190 pub(crate) fn get_with_id(&self, key: &str) -> Option<(&str, u8)> {
191 self.0.get(KeyRef::new(key)).map(|(s, i)| (s.as_str(), *i))
192 }
193
194 pub fn get(&self, key: &str) -> Option<&str> {
200 self.0.get(KeyRef::new(key)).map(|(s, _)| s.as_str())
201 }
202
203 pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) -> Option<String> {
210 let id = context::id();
211 let value = value.into();
212
213 match self.0.entry(Key::from(key.into())) {
214 Occupied(mut e) => {
215 let entry = e.get_mut();
216 let old = replace(&mut entry.0, value);
217
218 entry.1 |= id;
219
220 let entry = e.get();
221
222 context::overridden(entry.1, e.key().as_ref(), &old, &entry.0);
223 Some(old)
224 }
225 Vacant(e) => {
226 e.insert((value, id));
227 None
228 }
229 }
230 }
231
232 #[inline]
235 pub fn shrink_to_fit(&mut self) {
236 self.0.shrink_to_fit();
237 }
238}
239
240pub struct Iter<'a>(map::Iter<'a, Key<'static>, (String, u8)>);
242
243pub struct IntoIter(map::IntoIter<Key<'static>, (String, u8)>);
245
246pub struct Keys<'a>(map::Keys<'a, Key<'static>, (String, u8)>);
248
249impl<'a> Iterator for Iter<'a> {
250 type Item = (&'a str, &'a str);
251
252 fn next(&mut self) -> Option<Self::Item> {
253 self.0.next().map(|(k, (v, _))| (k.as_ref(), v.as_str()))
254 }
255}
256
257impl Iterator for IntoIter {
258 type Item = (String, String);
259
260 fn next(&mut self) -> Option<Self::Item> {
261 self.0.next().map(|(k, (v, _))| (k.0.into_owned(), v))
262 }
263}
264
265impl<'a> IntoIterator for &'a Settings {
266 type Item = (&'a str, &'a str);
267 type IntoIter = Iter<'a>;
268
269 #[inline]
270 fn into_iter(self) -> Self::IntoIter {
271 Iter(self.0.iter())
272 }
273}
274
275impl IntoIterator for Settings {
276 type Item = (String, String);
277 type IntoIter = IntoIter;
278
279 #[inline]
280 fn into_iter(self) -> Self::IntoIter {
281 IntoIter(self.0.into_iter())
282 }
283}
284
285impl<'a> Iterator for Keys<'a> {
286 type Item = &'a str;
287
288 #[inline]
289 fn next(&mut self) -> Option<Self::Item> {
290 self.0.next().map(AsRef::as_ref)
291 }
292}
293
294impl Debug for Settings {
295 #[inline]
296 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
297 Debug::fmt(&self.0, f)
298 }
299}
300
301impl Display for Settings {
302 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
303 let mut pairs = self.0.iter();
304
305 if let Some((key, (value, _))) = pairs.next() {
306 write!(f, "{key}: {value}")?;
307
308 for (key, (value, _)) in pairs {
309 f.write_str(", ")?;
310 write!(f, "{key}: {value}")?;
311 }
312 }
313
314 Ok(())
315 }
316}
317
318impl Merge for Settings {
319 fn merge(&mut self, other: &Self) {
320 let id = context::id();
323
324 for (key, (value, _)) in &other.0 {
325 self.0.insert(key.clone(), (value.clone(), id));
326 }
327 }
328}