1use std::borrow::{Borrow, Cow};
2use std::fmt;
3use std::hash::Hash;
4use std::iter::FusedIterator;
5use std::ops::{Index, IndexMut};
6
7use crate::Value;
8
9#[derive(Clone, Default)]
11pub struct Compound<S = String> {
12 map: Map<S>,
13}
14
15#[cfg(not(feature = "preserve_order"))]
16type Map<S> = std::collections::BTreeMap<S, Value<S>>;
17
18#[cfg(feature = "preserve_order")]
19type Map<S> = indexmap::IndexMap<S, Value<S>>;
20
21impl<S: fmt::Debug> fmt::Debug for Compound<S> {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 self.map.fmt(f)
24 }
25}
26
27impl<S> PartialEq for Compound<S>
28where
29 S: Ord + Hash,
30{
31 fn eq(&self, other: &Self) -> bool {
32 self.map == other.map
33 }
34}
35
36#[cfg(feature = "serde")]
37impl<Str> serde::Serialize for Compound<Str>
38where
39 Str: Ord + Hash + serde::Serialize,
40{
41 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: serde::Serializer,
44 {
45 self.map.serialize(serializer)
46 }
47}
48
49#[cfg(feature = "serde")]
50impl<'de, S> serde::Deserialize<'de> for Compound<S>
51where
52 S: Ord + Hash + serde::Deserialize<'de>,
53{
54 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55 where
56 D: serde::Deserializer<'de>,
57 {
58 Map::<S>::deserialize(deserializer).map(|map| Self { map })
59 }
60
61 fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
62 where
63 D: serde::Deserializer<'de>,
64 {
65 Map::<S>::deserialize_in_place(deserializer, &mut place.map)
66 }
67}
68
69impl<S> Compound<S> {
70 pub fn new() -> Self {
71 Self { map: Map::new() }
72 }
73
74 pub fn with_capacity(cap: usize) -> Self {
75 Self {
76 #[cfg(not(feature = "preserve_order"))]
77 map: {
78 let _ = cap;
80 Map::new()
81 },
82 #[cfg(feature = "preserve_order")]
83 map: Map::with_capacity(cap),
84 }
85 }
86
87 pub fn clear(&mut self) {
88 self.map.clear();
89 }
90}
91
92impl<S> Compound<S>
93where
94 S: Ord + Hash,
95{
96 pub fn get<Q>(&self, k: &Q) -> Option<&Value<S>>
97 where
98 Q: ?Sized + AsBorrowed<S>,
99 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
100 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
101 {
102 self.map.get(k.as_borrowed())
103 }
104
105 pub fn contains_key<Q>(&self, k: &Q) -> bool
106 where
107 Q: ?Sized + AsBorrowed<S>,
108 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
109 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
110 {
111 self.map.contains_key(k.as_borrowed())
112 }
113
114 pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut Value<S>>
115 where
116 Q: ?Sized + AsBorrowed<S>,
117 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
118 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
119 {
120 self.map.get_mut(k.as_borrowed())
121 }
122
123 pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&S, &Value<S>)>
124 where
125 Q: ?Sized + AsBorrowed<S>,
126 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
127 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
128 {
129 self.map.get_key_value(k.as_borrowed())
130 }
131
132 pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<Value<S>>
133 where
134 K: Into<S>,
135 V: Into<Value<S>>,
136 {
137 self.map.insert(k.into(), v.into())
138 }
139
140 pub fn remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
141 where
142 Q: ?Sized + AsBorrowed<S>,
143 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
144 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
145 {
146 #[cfg(feature = "preserve_order")]
147 return self.swap_remove(k);
148 #[cfg(not(feature = "preserve_order"))]
149 return self.map.remove(k.as_borrowed());
150 }
151
152 #[cfg(feature = "preserve_order")]
153 pub fn swap_remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
154 where
155 Q: ?Sized + AsBorrowed<S>,
156 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
157 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
158 {
159 self.map.swap_remove(k.as_borrowed())
160 }
161
162 #[cfg(feature = "preserve_order")]
163 pub fn shift_remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
164 where
165 Q: ?Sized + AsBorrowed<S>,
166 <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
167 S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
168 {
169 self.map.shift_remove(k.as_borrowed())
170 }
171
172 pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
173 where
174 S: Borrow<Q>,
175 Q: ?Sized + Ord + Hash,
176 {
177 #[cfg(feature = "preserve_order")]
178 return self.swap_remove_entry(k);
179 #[cfg(not(feature = "preserve_order"))]
180 return self.map.remove_entry(k);
181 }
182
183 #[cfg(feature = "preserve_order")]
184 pub fn swap_remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
185 where
186 S: Borrow<Q>,
187 Q: ?Sized + Ord + Hash,
188 {
189 self.map.swap_remove_entry(k)
190 }
191
192 #[cfg(feature = "preserve_order")]
193 pub fn shift_remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
194 where
195 S: Borrow<Q>,
196 Q: ?Sized + Ord + Hash,
197 {
198 self.map.shift_remove_entry(k)
199 }
200
201 pub fn append(&mut self, other: &mut Self) {
202 #[cfg(not(feature = "preserve_order"))]
203 self.map.append(&mut other.map);
204
205 #[cfg(feature = "preserve_order")]
206 for (k, v) in std::mem::take(&mut other.map) {
207 self.map.insert(k, v);
208 }
209 }
210
211 pub fn entry<K>(&mut self, k: K) -> Entry<S>
212 where
213 K: Into<S>,
214 {
215 #[cfg(not(feature = "preserve_order"))]
216 use std::collections::btree_map::Entry as EntryImpl;
217
218 #[cfg(feature = "preserve_order")]
219 use indexmap::map::Entry as EntryImpl;
220
221 match self.map.entry(k.into()) {
222 EntryImpl::Vacant(ve) => Entry::Vacant(VacantEntry { entry: ve }),
223 EntryImpl::Occupied(oe) => Entry::Occupied(OccupiedEntry { entry: oe }),
224 }
225 }
226
227 pub fn len(&self) -> usize {
228 self.map.len()
229 }
230
231 pub fn is_empty(&self) -> bool {
232 self.map.is_empty()
233 }
234
235 pub fn iter(&self) -> Iter<S> {
236 Iter {
237 iter: self.map.iter(),
238 }
239 }
240
241 pub fn iter_mut(&mut self) -> IterMut<S> {
242 IterMut {
243 iter: self.map.iter_mut(),
244 }
245 }
246
247 pub fn keys(&self) -> Keys<S> {
248 Keys {
249 iter: self.map.keys(),
250 }
251 }
252
253 pub fn values(&self) -> Values<S> {
254 Values {
255 iter: self.map.values(),
256 }
257 }
258
259 pub fn values_mut(&mut self) -> ValuesMut<S> {
260 ValuesMut {
261 iter: self.map.values_mut(),
262 }
263 }
264
265 pub fn retain<F>(&mut self, f: F)
266 where
267 F: FnMut(&S, &mut Value<S>) -> bool,
268 {
269 self.map.retain(f)
270 }
271
272 pub fn merge(&mut self, other: Compound<S>) {
307 for (k, v) in other {
308 match (self.entry(k), v) {
309 (Entry::Occupied(mut oe), Value::Compound(other)) => {
310 if let Value::Compound(this) = oe.get_mut() {
311 this.merge(other);
313 }
314 }
315 (Entry::Occupied(mut oe), value) => {
316 oe.insert(value);
317 }
318 (Entry::Vacant(ve), value) => {
319 ve.insert(value);
320 }
321 }
322 }
323 }
324}
325
326pub trait AsBorrowed<S> {
329 type Borrowed: ?Sized;
330
331 fn as_borrowed(&self) -> &Self::Borrowed;
332}
333
334impl<Q: ?Sized> AsBorrowed<String> for Q
335where
336 String: Borrow<Q>,
337{
338 type Borrowed = Q;
339
340 #[inline]
341 fn as_borrowed(&self) -> &Q {
342 self
343 }
344}
345
346impl<'a, Q: ?Sized> AsBorrowed<Cow<'a, str>> for Q
347where
348 Cow<'a, str>: Borrow<Q>,
349{
350 type Borrowed = Q;
351
352 #[inline]
353 fn as_borrowed(&self) -> &Q {
354 self
355 }
356}
357
358#[cfg(feature = "java_string")]
359impl<Q: ?Sized> AsBorrowed<java_string::JavaString> for Q
360where
361 for<'a> &'a Q: Into<&'a java_string::JavaStr>,
362{
363 type Borrowed = java_string::JavaStr;
364
365 fn as_borrowed(&self) -> &Self::Borrowed {
366 self.into()
367 }
368}
369
370#[cfg(feature = "java_string")]
371impl<Q: ?Sized> AsBorrowed<Cow<'_, java_string::JavaStr>> for Q
372where
373 for<'a> &'a Q: Into<&'a java_string::JavaStr>,
374{
375 type Borrowed = java_string::JavaStr;
376
377 fn as_borrowed(&self) -> &Self::Borrowed {
378 self.into()
379 }
380}
381
382impl<S> Extend<(S, Value<S>)> for Compound<S>
383where
384 S: Ord + Hash,
385{
386 fn extend<T>(&mut self, iter: T)
387 where
388 T: IntoIterator<Item = (S, Value<S>)>,
389 {
390 self.map.extend(iter)
391 }
392}
393
394impl<S> FromIterator<(S, Value<S>)> for Compound<S>
395where
396 S: Ord + Hash,
397{
398 fn from_iter<T>(iter: T) -> Self
399 where
400 T: IntoIterator<Item = (S, Value<S>)>,
401 {
402 Self {
403 map: Map::from_iter(iter),
404 }
405 }
406}
407
408pub enum Entry<'a, S = String> {
409 Vacant(VacantEntry<'a, S>),
410 Occupied(OccupiedEntry<'a, S>),
411}
412
413impl<'a, S> Entry<'a, S>
414where
415 S: Hash + Ord,
416{
417 pub fn key(&self) -> &S {
418 match self {
419 Entry::Vacant(ve) => ve.key(),
420 Entry::Occupied(oe) => oe.key(),
421 }
422 }
423
424 pub fn or_insert<V: Into<Value<S>>>(self, default: V) -> &'a mut Value<S> {
425 match self {
426 Entry::Vacant(ve) => ve.insert(default),
427 Entry::Occupied(oe) => oe.into_mut(),
428 }
429 }
430
431 pub fn or_insert_with<F, V>(self, default: F) -> &'a mut Value<S>
432 where
433 F: FnOnce() -> V,
434 V: Into<Value<S>>,
435 {
436 match self {
437 Entry::Vacant(ve) => ve.insert(default()),
438 Entry::Occupied(oe) => oe.into_mut(),
439 }
440 }
441
442 pub fn and_modify<F>(self, f: F) -> Self
443 where
444 F: FnOnce(&mut Value<S>),
445 {
446 match self {
447 Entry::Vacant(ve) => Entry::Vacant(ve),
448 Entry::Occupied(mut oe) => {
449 f(oe.get_mut());
450 Entry::Occupied(oe)
451 }
452 }
453 }
454}
455
456impl<S> fmt::Debug for Entry<'_, S>
457where
458 S: fmt::Debug + Ord,
459{
460 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461 match self {
462 Self::Vacant(entry) => f.debug_tuple("Vacant").field(entry).finish(),
463 Self::Occupied(entry) => f.debug_tuple("Occupied").field(entry).finish(),
464 }
465 }
466}
467
468pub struct VacantEntry<'a, S = String> {
469 #[cfg(not(feature = "preserve_order"))]
470 entry: std::collections::btree_map::VacantEntry<'a, S, Value<S>>,
471 #[cfg(feature = "preserve_order")]
472 entry: indexmap::map::VacantEntry<'a, S, Value<S>>,
473}
474
475impl<'a, S> VacantEntry<'a, S>
476where
477 S: Ord + Hash,
478{
479 pub fn key(&self) -> &S {
480 self.entry.key()
481 }
482
483 pub fn insert<V: Into<Value<S>>>(self, v: V) -> &'a mut Value<S> {
484 self.entry.insert(v.into())
485 }
486}
487
488impl<S> fmt::Debug for VacantEntry<'_, S>
489where
490 S: fmt::Debug + Ord,
491{
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 f.debug_struct("VacantEntry")
494 .field("entry", &self.entry)
495 .finish()
496 }
497}
498
499pub struct OccupiedEntry<'a, S = String> {
500 #[cfg(not(feature = "preserve_order"))]
501 entry: std::collections::btree_map::OccupiedEntry<'a, S, Value<S>>,
502 #[cfg(feature = "preserve_order")]
503 entry: indexmap::map::OccupiedEntry<'a, S, Value<S>>,
504}
505
506impl<'a, S> OccupiedEntry<'a, S>
507where
508 S: Hash + Ord,
509{
510 pub fn key(&self) -> &S {
511 self.entry.key()
512 }
513
514 pub fn get(&self) -> &Value<S> {
515 self.entry.get()
516 }
517
518 pub fn get_mut(&mut self) -> &mut Value<S> {
519 self.entry.get_mut()
520 }
521
522 pub fn into_mut(self) -> &'a mut Value<S> {
523 self.entry.into_mut()
524 }
525
526 pub fn insert<V: Into<Value<S>>>(&mut self, v: V) -> Value<S> {
527 self.entry.insert(v.into())
528 }
529
530 pub fn remove(self) -> Value<S> {
531 #[cfg(feature = "preserve_order")]
532 return self.swap_remove();
533 #[cfg(not(feature = "preserve_order"))]
534 return self.entry.remove();
535 }
536
537 #[cfg(feature = "preserve_order")]
538 pub fn swap_remove(self) -> Value<S> {
539 self.entry.swap_remove()
540 }
541
542 #[cfg(feature = "preserve_order")]
543 pub fn shift_remove(self) -> Value<S> {
544 self.entry.shift_remove()
545 }
546}
547
548impl<S> fmt::Debug for OccupiedEntry<'_, S>
549where
550 S: fmt::Debug + Ord,
551{
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 f.debug_struct("OccupiedEntry")
554 .field("entry", &self.entry)
555 .finish()
556 }
557}
558
559impl<S, Q> Index<&'_ Q> for Compound<S>
560where
561 S: Borrow<Q> + Ord + Hash,
562 Q: ?Sized + Ord + Hash,
563{
564 type Output = Value<S>;
565
566 fn index(&self, index: &Q) -> &Self::Output {
567 self.map.index(index)
568 }
569}
570
571impl<S, Q> IndexMut<&'_ Q> for Compound<S>
572where
573 S: Borrow<Q> + Hash + Ord,
574 Q: ?Sized + Ord + Hash,
575{
576 fn index_mut(&mut self, index: &Q) -> &mut Self::Output {
577 self.map.get_mut(index).expect("no entry found for key")
578 }
579}
580
581macro_rules! impl_iterator_traits {
582 (($name:ident $($generics:tt)*) => $item:ty) => {
583 impl $($generics)* Iterator for $name $($generics)* {
584 type Item = $item;
585 #[inline]
586 fn next(&mut self) -> Option<Self::Item> {
587 self.iter.next()
588 }
589 #[inline]
590 fn size_hint(&self) -> (usize, Option<usize>) {
591 self.iter.size_hint()
592 }
593 }
594
595 #[cfg(feature = "preserve_order")]
596 impl $($generics)* DoubleEndedIterator for $name $($generics)* {
597 #[inline]
598 fn next_back(&mut self) -> Option<Self::Item> {
599 self.iter.next_back()
600 }
601 }
602
603 impl $($generics)* ExactSizeIterator for $name $($generics)* {
604 #[inline]
605 fn len(&self) -> usize {
606 self.iter.len()
607 }
608 }
609
610 impl $($generics)* FusedIterator for $name $($generics)* {}
611 }
612}
613
614impl<'a, S> IntoIterator for &'a Compound<S> {
615 type Item = (&'a S, &'a Value<S>);
616 type IntoIter = Iter<'a, S>;
617
618 fn into_iter(self) -> Self::IntoIter {
619 Iter {
620 iter: self.map.iter(),
621 }
622 }
623}
624
625#[derive(Clone, Debug)]
626pub struct Iter<'a, S = String> {
627 #[cfg(not(feature = "preserve_order"))]
628 iter: std::collections::btree_map::Iter<'a, S, Value<S>>,
629 #[cfg(feature = "preserve_order")]
630 iter: indexmap::map::Iter<'a, S, Value<S>>,
631}
632
633impl_iterator_traits!((Iter<'a, S>) => (&'a S, &'a Value<S>));
634
635impl<'a, S> IntoIterator for &'a mut Compound<S> {
636 type Item = (&'a S, &'a mut Value<S>);
637 type IntoIter = IterMut<'a, S>;
638
639 fn into_iter(self) -> Self::IntoIter {
640 IterMut {
641 iter: self.map.iter_mut(),
642 }
643 }
644}
645
646#[derive(Debug)]
647pub struct IterMut<'a, S = String> {
648 #[cfg(not(feature = "preserve_order"))]
649 iter: std::collections::btree_map::IterMut<'a, S, Value<S>>,
650 #[cfg(feature = "preserve_order")]
651 iter: indexmap::map::IterMut<'a, S, Value<S>>,
652}
653
654impl_iterator_traits!((IterMut<'a, S>) => (&'a S, &'a mut Value<S>));
655
656impl<S> IntoIterator for Compound<S> {
657 type Item = (S, Value<S>);
658 type IntoIter = IntoIter<S>;
659
660 fn into_iter(self) -> Self::IntoIter {
661 IntoIter {
662 iter: self.map.into_iter(),
663 }
664 }
665}
666
667#[derive(Debug)]
668pub struct IntoIter<S = String> {
669 #[cfg(not(feature = "preserve_order"))]
670 iter: std::collections::btree_map::IntoIter<S, Value<S>>,
671 #[cfg(feature = "preserve_order")]
672 iter: indexmap::map::IntoIter<S, Value<S>>,
673}
674
675impl_iterator_traits!((IntoIter<S>) => (S, Value<S>));
676
677#[derive(Clone, Debug)]
678pub struct Keys<'a, S = String> {
679 #[cfg(not(feature = "preserve_order"))]
680 iter: std::collections::btree_map::Keys<'a, S, Value<S>>,
681 #[cfg(feature = "preserve_order")]
682 iter: indexmap::map::Keys<'a, S, Value<S>>,
683}
684
685impl_iterator_traits!((Keys<'a, S>) => &'a S);
686
687#[derive(Clone, Debug)]
688pub struct Values<'a, S = String> {
689 #[cfg(not(feature = "preserve_order"))]
690 iter: std::collections::btree_map::Values<'a, S, Value<S>>,
691 #[cfg(feature = "preserve_order")]
692 iter: indexmap::map::Values<'a, S, Value<S>>,
693}
694
695impl_iterator_traits!((Values<'a, S>) => &'a Value<S>);
696
697#[derive(Debug)]
698pub struct ValuesMut<'a, S = String> {
699 #[cfg(not(feature = "preserve_order"))]
700 iter: std::collections::btree_map::ValuesMut<'a, S, Value<S>>,
701 #[cfg(feature = "preserve_order")]
702 iter: indexmap::map::ValuesMut<'a, S, Value<S>>,
703}
704
705impl_iterator_traits!((ValuesMut<'a, S>) => &'a mut Value<S>);
706
707#[cfg(test)]
708mod tests {
709 #[cfg(feature = "preserve_order")]
710 #[test]
711 fn compound_preserves_order() {
712 use super::*;
713
714 let letters = ["g", "b", "d", "e", "h", "z", "m", "a", "q"];
715
716 let mut c = Compound::<String>::new();
717 for l in letters {
718 c.insert(l, 0_i8);
719 }
720
721 for (k, l) in c.keys().zip(letters) {
722 assert_eq!(k, l);
723 }
724 }
725}