1use alloc::vec::{IntoIter as VecIter, Vec};
4use core::{
5 fmt::Debug,
6 hash::{Hash, Hasher},
7 mem,
8 slice::{Iter as SliceIter, IterMut as SliceIterMut},
9};
10
11use crate::Domain;
12
13#[derive(Debug, Clone)]
106pub struct DomainMap<T> {
107 data: Vec<(Domain, T)>,
108}
109
110impl<T> DomainMap<T> {
111 #[must_use]
113 pub const fn new() -> Self {
114 Self { data: Vec::new() }
115 }
116
117 #[must_use]
120 pub fn with_capacity(cap: usize) -> Self {
121 Self {
122 data: Vec::with_capacity(cap),
123 }
124 }
125
126 pub fn set(&mut self, domain: Domain, value: T) -> Option<T> {
147 for (k, v) in &mut self.data {
148 if *k == domain {
149 return Some(mem::replace(v, value));
150 }
151 }
152
153 self.data.push((domain, value));
154 None
155 }
156
157 #[must_use]
206 pub fn get(&self, domain: &Domain) -> Option<&T> {
207 let mut wildcard_result = None;
208
209 for (k, v) in &self.data {
210 if domain.matches(k).unwrap_or(false) {
211 if k.is_wildcard() {
212 wildcard_result = Some(v);
213 } else {
214 return Some(v);
215 }
216 }
217 }
218
219 wildcard_result
220 }
221
222 #[must_use]
273 pub fn get_mut(&mut self, domain: &Domain) -> Option<&mut T> {
274 let mut wildcard_result = None;
275
276 for (k, v) in &mut self.data {
277 if domain.matches(k).unwrap_or(false) {
278 if k.is_wildcard() {
279 wildcard_result = Some(v);
280 } else {
281 return Some(v);
282 }
283 }
284 }
285
286 wildcard_result
287 }
288
289 #[must_use]
314 pub fn get_eq(&self, domain: &Domain) -> Option<&T> {
315 for (k, v) in &self.data {
316 if domain == k {
317 return Some(v);
318 }
319 }
320
321 None
322 }
323
324 pub fn remove(&mut self, domain: &Domain) -> Option<T> {
355 for (i, (k, _)) in self.data.iter_mut().enumerate() {
356 if k == domain {
357 let (_, v) = self.data.swap_remove(i);
358 return Some(v);
359 }
360 }
361
362 None
363 }
364
365 pub fn clear(&mut self) {
387 self.data.clear();
388 }
389
390 #[must_use]
410 pub fn len(&self) -> usize {
411 self.data.len()
412 }
413
414 #[must_use]
434 pub fn is_empty(&self) -> bool {
435 self.len() == 0
436 }
437
438 #[must_use]
459 pub fn iter(&self) -> Iter<'_, T> {
460 <&Self as IntoIterator>::into_iter(self)
461 }
462
463 #[must_use]
484 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
485 <&mut Self as IntoIterator>::into_iter(self)
486 }
487}
488
489impl<T> Default for DomainMap<T> {
490 fn default() -> Self {
491 Self::with_capacity(4)
492 }
493}
494
495impl<T: PartialEq> PartialEq for DomainMap<T> {
496 fn eq(&self, other: &Self) -> bool {
497 if self.len() != other.len() {
498 return false;
499 }
500
501 self.iter()
502 .all(|(key, value)| other.get_eq(key) == Some(value))
503 }
504}
505
506impl<T: Eq> Eq for DomainMap<T> {}
507
508impl<T: Hash> Hash for DomainMap<T> {
509 fn hash<H: Hasher>(&self, state: &mut H) {
510 let mut sorted = self.data.iter().collect::<Vec<&(Domain, T)>>();
511 sorted.sort_unstable_by_key(|(domain, _)| domain);
512
513 for element in sorted {
514 (*element).hash(state);
515 }
516 }
517}
518
519impl<T> FromIterator<(Domain, T)> for DomainMap<T> {
520 fn from_iter<I: IntoIterator<Item = (Domain, T)>>(iter: I) -> Self {
521 let iter = iter.into_iter();
522 let mut map = Self::with_capacity(iter.size_hint().0);
523
524 for (domain, value) in iter {
525 map.set(domain, value);
526 }
527
528 map
529 }
530}
531
532impl<T> Extend<(Domain, T)> for DomainMap<T> {
533 fn extend<I: IntoIterator<Item = (Domain, T)>>(&mut self, iter: I) {
534 for (domain, value) in iter {
535 self.set(domain, value);
536 }
537 }
538}
539
540impl<T> IntoIterator for DomainMap<T> {
541 type IntoIter = IntoIter<T>;
542 type Item = (Domain, T);
543
544 fn into_iter(self) -> Self::IntoIter {
545 IntoIter {
546 inner: self.data.into_iter(),
547 }
548 }
549}
550
551impl<'a, T: 'a> IntoIterator for &'a DomainMap<T> {
552 type IntoIter = Iter<'a, T>;
553 type Item = (&'a Domain, &'a T);
554
555 fn into_iter(self) -> Self::IntoIter {
556 Iter {
557 inner: self.data.iter(),
558 }
559 }
560}
561
562impl<'a, T: 'a> IntoIterator for &'a mut DomainMap<T> {
563 type IntoIter = IterMut<'a, T>;
564 type Item = (&'a Domain, &'a mut T);
565
566 fn into_iter(self) -> Self::IntoIter {
567 IterMut {
568 inner: self.data.iter_mut(),
569 }
570 }
571}
572
573pub struct IntoIter<T> {
574 inner: VecIter<(Domain, T)>,
575}
576
577impl<T> Iterator for IntoIter<T> {
578 type Item = (Domain, T);
579
580 fn next(&mut self) -> Option<Self::Item> {
581 self.inner.next()
582 }
583}
584
585pub struct Iter<'a, T: 'a> {
586 inner: SliceIter<'a, (Domain, T)>,
587}
588
589impl<'a, T: 'a> Iterator for Iter<'a, T> {
590 type Item = (&'a Domain, &'a T);
591
592 fn next(&mut self) -> Option<Self::Item> {
593 self.inner.next().map(|(k, v)| (k, v))
594 }
595}
596
597pub struct IterMut<'a, T: 'a> {
598 inner: SliceIterMut<'a, (Domain, T)>,
599}
600
601impl<'a, T: 'a> Iterator for IterMut<'a, T> {
602 type Item = (&'a Domain, &'a mut T);
603
604 fn next(&mut self) -> Option<Self::Item> {
605 self.inner.next().map(|(k, v)| (&*k, v))
606 }
607}
608
609#[cfg(test)]
610mod tests {
611 use alloc::format;
612
613 use super::*;
614
615 #[test]
616 fn domainmap_new() {
617 for map in [
618 DomainMap::<()>::new(),
619 DomainMap::<()>::default(),
620 DomainMap::<()>::with_capacity(8),
621 ] {
622 assert!(map.is_empty());
623 assert_eq!(map.len(), 0);
624
625 assert!(map
626 .get(&Domain::reference("example.com").unwrap())
627 .is_none());
628 }
629 }
630
631 #[test]
632 fn domainmap_get() {
633 let mut map = DomainMap::<u32>::new();
634
635 assert_eq!(map.get(&Domain::reference("example.com").unwrap()), None);
636 assert_eq!(
637 map.get(&Domain::reference("foo.example.com").unwrap()),
638 None
639 );
640
641 map.set(Domain::presented("example.com").unwrap(), 1);
642 map.set(Domain::presented("*.example.com").unwrap(), 10);
643
644 assert_eq!(
645 map.get(&Domain::reference("example.com").unwrap()),
646 Some(&1)
647 );
648 assert_eq!(
649 map.get(&Domain::reference("foo.example.com").unwrap()),
650 Some(&10)
651 );
652 }
653
654 #[test]
655 fn domainmap_get_mut() {
656 let mut map = DomainMap::<u32>::new();
657
658 assert_eq!(
659 map.get_mut(&Domain::reference("example.com").unwrap()),
660 None
661 );
662 assert_eq!(
663 map.get_mut(&Domain::reference("foo.example.com").unwrap()),
664 None
665 );
666
667 map.set(Domain::presented("example.com").unwrap(), 1);
668 map.set(Domain::presented("*.example.com").unwrap(), 10);
669
670 assert_eq!(
671 map.get_mut(&Domain::reference("example.com").unwrap()),
672 Some(&mut 1)
673 );
674
675 let val = map
676 .get_mut(&Domain::reference("example.com").unwrap())
677 .unwrap();
678 *val += 100;
679
680 let foo_val = map
681 .get_mut(&Domain::reference("foo.example.com").unwrap())
682 .unwrap();
683 *foo_val += 100;
684
685 assert_eq!(
686 map.get_mut(&Domain::reference("example.com").unwrap()),
687 Some(&mut 101)
688 );
689 assert_eq!(
690 map.get_mut(&Domain::reference("foo.example.com").unwrap()),
691 Some(&mut 110)
692 );
693 }
694
695 #[test]
696 fn domainmap_get_eq() {
697 let mut map = DomainMap::<u32>::new();
698
699 assert_eq!(
700 map.get_eq(&Domain::presented("*.example.com").unwrap()),
701 None
702 );
703 assert_eq!(
704 map.get_eq(&Domain::reference("foo.example.com").unwrap()),
705 None
706 );
707
708 map.set(Domain::presented("*.example.com").unwrap(), 1);
709
710 assert_eq!(
711 map.get_eq(&Domain::presented("*.example.com").unwrap()),
712 Some(&1)
713 );
714 assert_eq!(
715 map.get_eq(&Domain::reference("foo.example.com").unwrap()),
716 None
717 );
718 }
719
720 #[test]
721 fn domainmap_set() {
722 let mut map = DomainMap::<u32>::new();
723
724 assert_eq!(map.set(Domain::presented("example.com").unwrap(), 1), None);
725 assert_eq!(
726 map.set(Domain::presented("*.example.com").unwrap(), 10),
727 None
728 );
729
730 assert_eq!(
731 map.get(&Domain::reference("example.com").unwrap()),
732 Some(&1)
733 );
734 assert_eq!(
735 map.get(&Domain::reference("foo.example.com").unwrap()),
736 Some(&10)
737 );
738
739 assert_eq!(
740 map.set(Domain::presented("*.example.com").unwrap(), 20),
741 Some(10)
742 );
743 assert_eq!(
744 map.set(Domain::presented("example.com").unwrap(), 2),
745 Some(1)
746 );
747 assert_eq!(
748 map.set(Domain::presented("foo.example.com").unwrap(), 200),
749 None
750 );
751
752 assert_eq!(
753 map.get(&Domain::reference("example.com").unwrap()),
754 Some(&2)
755 );
756 assert_eq!(
757 map.get(&Domain::reference("foo.example.com").unwrap()),
758 Some(&200)
759 );
760 }
761
762 #[test]
763 fn domainmap_remove() {
764 let mut map = DomainMap::<u32>::new();
765
766 map.set(Domain::presented("example.com").unwrap(), 1);
767 map.set(Domain::presented("*.example.com").unwrap(), 10);
768
769 assert_eq!(map.len(), 2);
770
771 assert_eq!(
772 map.remove(&Domain::presented("example.com").unwrap()),
773 Some(1)
774 );
775 assert_eq!(
776 map.remove(&Domain::presented("foo.example.com").unwrap()),
777 None
778 );
779
780 assert_eq!(map.len(), 1);
781 assert_eq!(map.get(&Domain::reference("example.com").unwrap()), None);
782 assert_eq!(
783 map.get(&Domain::reference("foo.example.com").unwrap()),
784 Some(&10)
785 );
786
787 assert_eq!(
788 map.remove(&Domain::presented("*.example.com").unwrap()),
789 Some(10)
790 );
791
792 assert_eq!(map.len(), 0);
793 assert_eq!(
794 map.get(&Domain::reference("foo.example.com").unwrap()),
795 None
796 );
797 }
798
799 #[test]
800 fn domainmap_len_clear() {
801 let mut map = DomainMap::<u32>::new();
802
803 assert!(map.is_empty());
804 assert_eq!(map.len(), 0);
805
806 map.set(Domain::presented("example.com").unwrap(), 1);
807 map.set(Domain::presented("*.example.com").unwrap(), 10);
808 map.set(Domain::presented("foo.example.com").unwrap(), 100);
809
810 assert!(!map.is_empty());
811 assert_eq!(map.len(), 3);
812
813 map.clear();
814
815 assert!(map.is_empty());
816 assert_eq!(map.len(), 0);
817 }
818
819 #[test]
820 fn domainmap_iter() {
821 let mut map = DomainMap::<u32>::new();
822
823 let a = Domain::presented("example.com").unwrap();
824 let b = Domain::presented("*.example.com").unwrap();
825 let c = Domain::presented("foo.example.com").unwrap();
826
827 map.set(a.clone(), 1);
828 map.set(b.clone(), 10);
829 map.set(c.clone(), 100);
830
831 #[allow(clippy::explicit_iter_loop)]
832 for (domain, value) in map.iter() {
833 assert!(
835 (*domain == a && *value == 1)
836 || (*domain == b && *value == 10)
837 || (*domain == c && *value == 100)
838 );
839 }
840
841 for (domain, value) in &map {
842 assert!(
844 (*domain == a && *value == 1)
845 || (*domain == b && *value == 10)
846 || (*domain == c && *value == 100)
847 );
848 }
849
850 #[allow(clippy::explicit_iter_loop)]
851 for (domain, value) in map.iter_mut() {
852 assert!(
854 (*domain == a && *value == 1)
855 || (*domain == b && *value == 10)
856 || (*domain == c && *value == 100)
857 );
858
859 *value += 300;
860 }
861 for (domain, value) in &mut map {
862 assert!(
864 (*domain == a && *value == 301)
865 || (*domain == b && *value == 310)
866 || (*domain == c && *value == 400)
867 );
868
869 *value += 700;
870 }
871
872 #[allow(clippy::explicit_into_iter_loop)]
873 for (domain, value) in map.clone().into_iter() {
874 assert!(
876 (domain == a && value == 1001)
877 || (domain == b && value == 1010)
878 || (domain == c && value == 1100)
879 );
880
881 drop(domain);
882 }
883
884 for (domain, value) in map {
885 assert!(
887 (domain == a && value == 1001)
888 || (domain == b && value == 1010)
889 || (domain == c && value == 1100)
890 );
891
892 drop(domain);
893 }
894
895 map = DomainMap::<u32>::new();
896
897 let a = Domain::presented("example.net").unwrap();
898 let b = Domain::presented("*.example.net").unwrap();
899 let c = Domain::presented("foo.example.net").unwrap();
900
901 map.set(a.clone(), 1);
902 map.set(b.clone(), 10);
903 map.set(c.clone(), 100);
904
905 for (domain, value) in &map {
906 assert!(
908 (*domain == a && *value == 1)
909 || (*domain == b && *value == 10)
910 || (*domain == c && *value == 100)
911 );
912 }
913
914 for (domain, value) in &mut map {
915 assert!(
917 (*domain == a && *value == 1)
918 || (*domain == b && *value == 10)
919 || (*domain == c && *value == 100)
920 );
921
922 *value += 1000;
923 }
924
925 for (domain, value) in map {
926 assert!(
928 (domain == a && value == 1001)
929 || (domain == b && value == 1010)
930 || (domain == c && value == 1100)
931 );
932
933 drop(domain);
934 }
935 }
936
937 #[test]
938 #[allow(clippy::many_single_char_names)]
939 fn domainmap_from_iter_extend() {
940 let a = Domain::presented("example.net").unwrap();
941 let b = Domain::presented("*.example.net").unwrap();
942 let c = Domain::presented("foo.example.net").unwrap();
943 let e = Domain::presented("example.com").unwrap();
944 let d = Domain::presented("bar.example.com").unwrap();
945
946 let mut map = DomainMap::<u32>::from_iter([(a, 1), (b, 10), (c, 100)]);
947
948 assert_eq!(map.len(), 3);
949
950 map.extend([(e, 1000), (d, 10000)]);
951
952 assert_eq!(map.len(), 5);
953 }
954
955 #[test]
956 fn domainmap_misc_traits() {
957 let mut map = DomainMap::<u32>::new();
958 let mut other = DomainMap::<u32>::new();
959
960 let a = Domain::presented("example.com").unwrap();
961 let b = Domain::presented("*.example.com").unwrap();
962 let c = Domain::presented("foo.example.com").unwrap();
963
964 map.set(a.clone(), 1);
965 map.set(b.clone(), 10);
966 map.set(c.clone(), 100);
967
968 other.set(c, 100);
969 other.set(b, 10);
970 other.set(a, 1);
971
972 assert!(format!("{map:?}").contains("DomainMap"));
973
974 let cloned = map.clone();
975 assert!(map == cloned);
976 assert!(map == other);
977 assert!(map == map);
978 assert!(map != DomainMap::new());
979 }
980}