1use rustc_hash::FxHashMap;
9use std::hash::Hash;
10
11#[derive(Debug, Clone)]
12pub struct SubsetMap<K, V> {
13 map: FxHashMap<K, Vec<SsmKeyValue<K, V>>>,
14}
15
16#[derive(Debug, Clone)]
17struct SsmKeyValue<K, V> {
18 key: Box<[K]>,
19 value: V,
20}
21
22impl<K, V> SsmKeyValue<K, V>
23where
24 K: Clone,
25{
26 fn ssmkv_new(key: impl AsRef<[K]>, value: V) -> Self {
27 Self {
28 key: key.as_ref().to_vec().into_boxed_slice(),
29 value,
30 }
31 }
32}
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
35pub enum GetOrIsSubsetOfKnownKey<T> {
36 HasValue(T),
37 IsSubset,
38 Neither,
39}
40
41#[derive(Debug, Copy, Clone, PartialEq, Eq)]
42pub enum SsmKeyExistedBeforeInsert {
43 Existed,
44 NotThere,
45}
46
47use GetOrIsSubsetOfKnownKey::*;
48
49impl<K, V> Default for SubsetMap<K, V>
50where
51 K: Clone + PartialEq + Ord + Hash,
52 V: Clone,
53{
54 fn default() -> Self {
55 Self::ssm_new()
56 }
57}
58
59impl<K, V> SubsetMap<K, V>
60where
61 K: Clone + PartialEq + Ord + Hash,
62 V: Clone,
63{
64 pub fn ssm_new() -> Self {
65 Self {
66 map: FxHashMap::default(),
67 }
68 }
69
70 pub fn ssm_insert(&mut self, mut key: impl AsMut<[K]>, val: V) -> SsmKeyExistedBeforeInsert {
72 key.as_mut().sort();
73 self.ssm_insert_ksorted(key.as_mut(), val)
74 }
75
76 pub fn ssm_insert_ksorted(
79 &mut self,
80 key: impl AsRef<[K]>,
81 val: V,
82 ) -> SsmKeyExistedBeforeInsert {
83 let mut key_existed = SsmKeyExistedBeforeInsert::NotThere;
84 for k in key.as_ref().iter().cloned() {
85 let keyvals_for_key_item = self.map.entry(k).or_default();
86 match keyvals_for_key_item
87 .binary_search_by(|probe| probe.key.as_ref().cmp(key.as_ref()))
88 {
89 Ok(pos) => {
90 key_existed = SsmKeyExistedBeforeInsert::Existed;
91 keyvals_for_key_item[pos] = SsmKeyValue::ssmkv_new(key.as_ref(), val.clone());
92 }
93 Err(pos) => {
94 keyvals_for_key_item
95 .insert(pos, SsmKeyValue::ssmkv_new(key.as_ref(), val.clone()));
96 }
97 }
98 }
99 key_existed
100 }
101
102 pub fn ssm_get_or_is_subset(&self, mut key: impl AsMut<[K]>) -> GetOrIsSubsetOfKnownKey<V> {
105 key.as_mut().sort();
106 self.ssm_get_or_is_subset_ksorted(key.as_mut())
107 }
108
109 pub fn ssm_get_or_is_subset_ksorted(
112 &self,
113 get_key: impl AsRef<[K]>,
114 ) -> GetOrIsSubsetOfKnownKey<V> {
115 let get_key = get_key.as_ref();
116 if get_key.is_empty() {
117 return match self.is_empty() {
118 true => Neither,
119 false => IsSubset,
120 };
121 }
122 match self.map.get(&get_key[0]) {
123 None => Neither,
124 Some(keyvals_for_key_item) => {
125 match keyvals_for_key_item
126 .binary_search_by(|probe| probe.key.as_ref().cmp(get_key.as_ref()))
127 {
128 Ok(pos) => HasValue(keyvals_for_key_item[pos].value.clone()),
129 Err(_) => {
130 for kv in keyvals_for_key_item.iter() {
131 if get_key.iter().all(|kitem| kv.key.contains(kitem)) {
132 return IsSubset;
133 }
134 }
135 Neither
136 }
137 }
138 }
139 }
140 }
141
142 pub fn is_empty(&self) -> bool {
143 self.map.is_empty()
144 }
145}