polars_utils/idx_map/
total_idx_map.rs1use hashbrown::hash_table::{
2 Entry as TEntry, HashTable, OccupiedEntry as TOccupiedEntry, VacantEntry as TVacantEntry,
3};
4
5use crate::IdxSize;
6use crate::aliases::PlRandomState;
7use crate::total_ord::{BuildHasherTotalExt, TotalEq, TotalHash};
8
9pub struct TotalIndexMap<K, V> {
11 table: HashTable<IdxSize>,
12 tuples: Vec<(K, V)>,
13 random_state: PlRandomState,
14}
15
16impl<K, V> Default for TotalIndexMap<K, V> {
17 fn default() -> Self {
18 Self {
19 table: HashTable::new(),
20 tuples: Vec::new(),
21 random_state: PlRandomState::default(),
22 }
23 }
24}
25
26impl<K: TotalHash + TotalEq, V> TotalIndexMap<K, V> {
27 pub fn reserve(&mut self, additional: usize) {
28 self.table.reserve(additional, |i| unsafe {
29 let tuple = self.tuples.get_unchecked(*i as usize);
30 self.random_state.tot_hash_one(&tuple.0)
31 });
32 self.tuples.reserve(additional);
33 }
34
35 pub fn len(&self) -> IdxSize {
36 self.tuples.len() as IdxSize
37 }
38
39 pub fn is_empty(&self) -> bool {
40 self.tuples.is_empty()
41 }
42
43 pub fn get(&self, key: &K) -> Option<&V> {
44 let idx = self.get_index_of(key)?;
45 unsafe { Some(&self.tuples.get_unchecked(idx as usize).1) }
46 }
47
48 pub fn get_index_of(&self, key: &K) -> Option<IdxSize> {
50 let hash = self.random_state.tot_hash_one(key);
51 self.table
52 .find(hash, |i| unsafe {
53 let t = self.tuples.get_unchecked(*i as usize);
54 hash == self.random_state.tot_hash_one(&t.0) && key.tot_eq(&t.0)
55 })
56 .copied()
57 }
58
59 pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
60 let hash = self.random_state.tot_hash_one(&key);
61 let entry = self.table.entry(
62 hash,
63 |i| unsafe {
64 let t = self.tuples.get_unchecked(*i as usize);
65 hash == self.random_state.tot_hash_one(&t.0) && key.tot_eq(&t.0)
66 },
67 |i| unsafe {
68 let t = self.tuples.get_unchecked(*i as usize);
69 self.random_state.tot_hash_one(&t.0)
70 },
71 );
72
73 match entry {
74 TEntry::Occupied(o) => Entry::Occupied(OccupiedEntry {
75 entry: o,
76 tuples: &mut self.tuples,
77 }),
78 TEntry::Vacant(v) => Entry::Vacant(VacantEntry {
79 key,
80 entry: v,
81 tuples: &mut self.tuples,
82 }),
83 }
84 }
85
86 pub fn push_unmapped_entry(&mut self, key: K, value: V) -> IdxSize {
90 let ret = self.tuples.len() as IdxSize;
91 self.tuples.push((key, value));
92 ret
93 }
94
95 #[inline(always)]
97 pub fn get_index(&self, idx: IdxSize) -> Option<(&K, &V)> {
98 let t = self.tuples.get(idx as usize)?;
99 Some((&t.0, &t.1))
100 }
101
102 #[inline(always)]
107 pub unsafe fn get_index_unchecked(&self, idx: IdxSize) -> (&K, &V) {
108 let t = unsafe { self.tuples.get_unchecked(idx as usize) };
109 (&t.0, &t.1)
110 }
111
112 pub fn iter_keys(&self) -> impl Iterator<Item = &K> {
114 self.tuples.iter().map(|t| &t.0)
115 }
116
117 pub fn iter_values(&self) -> impl Iterator<Item = &V> {
119 self.tuples.iter().map(|t| &t.1)
120 }
121}
122
123pub enum Entry<'a, K, V> {
124 Occupied(OccupiedEntry<'a, K, V>),
125 Vacant(VacantEntry<'a, K, V>),
126}
127
128pub struct OccupiedEntry<'a, K, V> {
129 entry: TOccupiedEntry<'a, IdxSize>,
130 tuples: &'a mut Vec<(K, V)>,
131}
132
133impl<'a, K, V> OccupiedEntry<'a, K, V> {
134 pub fn index(&self) -> IdxSize {
135 *self.entry.get()
136 }
137
138 pub fn into_mut(self) -> &'a mut V {
139 let idx = self.index();
140 unsafe { &mut self.tuples.get_unchecked_mut(idx as usize).1 }
141 }
142}
143
144pub struct VacantEntry<'a, K, V> {
145 key: K,
146 entry: TVacantEntry<'a, IdxSize>,
147 tuples: &'a mut Vec<(K, V)>,
148}
149
150impl<'a, K, V> VacantEntry<'a, K, V> {
151 pub fn index(&self) -> IdxSize {
152 self.tuples.len() as IdxSize
153 }
154
155 pub fn insert(self, value: V) -> &'a mut V {
156 unsafe {
157 let tuple_idx: IdxSize = self.tuples.len().try_into().unwrap();
158 self.tuples.push((self.key, value));
159 self.entry.insert(tuple_idx);
160 &mut self.tuples.last_mut().unwrap_unchecked().1
161 }
162 }
163}