1use crate::{
6 config::{ConsoliableWeight, KeyMngTrait},
7 search::{accumulate_weight_search, SearchDirection},
8 update::{ApplyOp, ApplyOpOutcome, InsertOp, RemoveOp},
9 Direction, NoWeight, SearchResult,
10};
11
12use super::{config::TreapMapConfig, node::Node};
13use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
14use rand::{RngCore, SeedableRng};
15use rand_xorshift::XorShiftRng;
16
17pub struct TreapMap<C: TreapMapConfig> {
21 #[cfg(test)]
23 pub(crate) root: Option<Box<Node<C>>>,
24 #[cfg(not(test))]
25 root: Option<Box<Node<C>>>,
26
27 ext_map: C::ExtMap,
31
32 rng: XorShiftRng,
35}
36
37impl<C: TreapMapConfig> MallocSizeOf for TreapMap<C>
38where
39 Node<C>: MallocSizeOf,
40 C::ExtMap: MallocSizeOf,
41{
42 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
43 self.root.size_of(ops) + self.ext_map.size_of(ops)
44 }
45}
46
47impl<C: TreapMapConfig> Default for TreapMap<C> {
48 fn default() -> Self { Self::new() }
49}
50
51impl<C: TreapMapConfig> TreapMap<C> {
52 pub fn new() -> TreapMap<C> {
53 TreapMap {
54 root: None,
55 rng: XorShiftRng::from_os_rng(),
56 ext_map: Default::default(),
57 }
58 }
59
60 pub fn new_with_rng(rng: XorShiftRng) -> TreapMap<C> {
61 TreapMap {
62 root: None,
63 rng,
64 ext_map: Default::default(),
65 }
66 }
67
68 pub fn len(&self) -> usize { self.ext_map.len() }
69
70 pub fn is_empty(&self) -> bool { self.ext_map.len() == 0 }
71
72 pub fn contains_key(&self, key: &C::SearchKey) -> bool {
73 self.get(key).is_some()
74 }
75
76 pub fn insert(
77 &mut self, key: C::SearchKey, value: C::Value, weight: C::Weight,
78 ) -> Option<C::Value> {
79 let sort_key = self.ext_map.make_sort_key(&key, &value);
80
81 let node = Node::new(key, value, sort_key, weight, self.rng.next_u64());
82
83 let (result, _, _) = Node::update_inner(
84 &mut self.root,
85 InsertOp {
86 node: Box::new(node),
87 ext_map: &mut self.ext_map,
88 },
89 );
90
91 result
92 }
93
94 pub fn remove(&mut self, key: &C::SearchKey) -> Option<C::Value> {
95 let sort_key = self.ext_map.get_sort_key(key)?;
96
97 let (result, _, _) = Node::update_inner(
98 &mut self.root,
99 RemoveOp {
100 key: (&sort_key, key),
101 ext_map: &mut self.ext_map,
102 },
103 );
104
105 result
106 }
107
108 pub fn update<U, I, T, E>(
124 &mut self, key: &C::SearchKey, update: U, insert: I,
125 ) -> Result<T, E>
126 where
127 U: FnOnce(&mut Node<C>) -> Result<ApplyOpOutcome<T>, E>,
128 I: FnOnce(&mut dyn RngCore) -> Result<(Node<C>, T), E>,
129 {
130 let sort_key = if let Some(sort_key) = self.ext_map.get_sort_key(key) {
131 sort_key
132 } else {
133 return match insert(&mut self.rng) {
134 Ok((node, ret)) => {
135 self.insert(node.key, node.value, node.weight);
136 Ok(ret)
137 }
138 Err(err) => Err(err),
139 };
140 };
141 let rng = &mut self.rng;
142 let (res, _, _) = Node::update_inner(
143 &mut self.root,
144 ApplyOp {
145 key: (&sort_key, key),
146 update,
147 insert: || insert(rng),
148 ext_map: &mut self.ext_map,
149 },
150 );
151 let (ret, maybe_node) = res?;
152 if let Some(node) = maybe_node {
153 self.insert(node.key, node.value, node.weight);
154 }
155 Ok(ret)
156 }
157
158 pub fn sum_weight(&self) -> C::Weight {
159 match &self.root {
160 Some(node) => node.sum_weight(),
161 None => C::Weight::empty(),
162 }
163 }
164
165 pub fn get(&self, key: &C::SearchKey) -> Option<&C::Value> {
166 let sort_key = self.ext_map.get_sort_key(key)?;
167 self.root.as_ref().and_then(|x| x.get(&sort_key, key))
168 }
169
170 #[inline]
171 pub fn get_by_weight(&self, weight: C::Weight) -> Option<&C::Value>
172 where C::Weight: Ord {
173 use SearchDirection::*;
174 self.search(|base, mid| {
175 if &weight < base {
176 Left
177 } else {
178 let right_base = C::Weight::consolidate(base, &mid.weight);
179 if weight < right_base {
180 Stop
181 } else {
182 Right(right_base)
183 }
184 }
185 })?
186 .maybe_value()
187 }
188
189 pub fn search<F>(&self, f: F) -> Option<SearchResult<'_, C, C::Weight>>
191 where F: FnMut(&C::Weight, &Node<C>) -> SearchDirection<C::Weight> {
192 Some(accumulate_weight_search(self.root.as_ref()?, f, |weight| {
193 weight
194 }))
195 }
196
197 pub fn search_no_weight<F>(
202 &self, mut f: F,
203 ) -> Option<SearchResult<'_, C, NoWeight>>
204 where F: FnMut(&Node<C>) -> SearchDirection<()> {
205 static NW: NoWeight = NoWeight;
206 Some(accumulate_weight_search(
207 self.root.as_ref()?,
208 |_, node| f(node).map_into(|_| NoWeight),
209 |_| &NW,
210 ))
211 }
212
213 pub fn iter(&self) -> Iter<'_, C> {
214 let mut iter = Iter { nodes: vec![] };
215 if let Some(ref n) = self.root {
216 iter.nodes.push(&**n);
217 iter.extend_path();
218 }
219 iter
220 }
221
222 pub fn iter_range(&self, key: &C::SearchKey) -> Iter<'_, C>
223 where C: TreapMapConfig<SortKey = ()> {
224 let mut iter = Iter { nodes: vec![] };
225 if let Some(ref n) = self.root {
226 iter.nodes.push(&**n);
227 iter.extend_path_with_key((&(), key));
228 }
229 iter
230 }
231
232 pub fn values(&self) -> impl Iterator<Item = &C::Value> {
233 self.iter().map(|node| &node.value)
234 }
235
236 pub fn key_values(
237 &self,
238 ) -> impl Iterator<Item = (&C::SearchKey, &C::Value)> {
239 self.iter().map(|node| (&node.key, &node.value))
240 }
241
242 #[cfg(any(test, feature = "testonly_code"))]
243 pub fn assert_consistency(&self)
244 where C::Weight: std::fmt::Debug {
245 if let Some(node) = self.root.as_ref() {
246 node.assert_consistency()
247 }
248 }
249}
250
251pub struct Iter<'a, C: TreapMapConfig> {
252 nodes: Vec<&'a Node<C>>,
253}
254
255impl<'a, C: TreapMapConfig> Clone for Iter<'a, C> {
256 fn clone(&self) -> Self {
257 Self {
258 nodes: self.nodes.clone(),
259 }
260 }
261}
262
263impl<'a, C: TreapMapConfig> Iter<'a, C> {
264 fn extend_path(&mut self) {
265 loop {
266 let node = *self.nodes.last().unwrap();
267 match node.left {
268 None => return,
269 Some(ref n) => self.nodes.push(&**n),
270 }
271 }
272 }
273
274 fn extend_path_with_key(&mut self, key: (&C::SortKey, &C::SearchKey)) {
275 loop {
276 let node = *self.nodes.last().unwrap();
277 match C::next_node_dir(key, (&node.sort_key, &node.key)) {
278 Some(Direction::Left) => {
279 if let Some(left) = &node.left {
280 self.nodes.push(left);
281 } else {
282 return;
283 }
284 }
285 None => {
286 return;
287 }
288 Some(Direction::Right) => {
289 let node = self.nodes.pop().unwrap();
290 if let Some(right) = &node.right {
291 self.nodes.push(right);
292 } else {
293 return;
294 }
295 }
296 }
297 }
298 }
299}
300
301impl<'a, C: TreapMapConfig> Iterator for Iter<'a, C> {
302 type Item = &'a Node<C>;
303
304 fn next(&mut self) -> Option<Self::Item> {
305 match self.nodes.pop() {
306 None => None,
307 Some(node) => {
308 if let Some(ref n) = node.right {
309 self.nodes.push(&**n);
310 self.extend_path();
311 }
312 Some(node)
313 }
314 }
315 }
316}