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