1use super::{
6 config::{ConsoliableWeight, Direction, TreapMapConfig},
7 update::{OpResult, TreapNodeUpdate},
8};
9
10use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
11use std::mem;
12
13#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
21pub struct Node<C: TreapMapConfig> {
22 pub key: C::SearchKey,
25
26 pub value: C::Value,
28
29 pub sort_key: C::SortKey,
32
33 pub weight: C::Weight,
36
37 pub(crate) sum_weight: C::Weight,
40
41 priority: u64,
44
45 pub(crate) left: Option<Box<Node<C>>>,
47
48 pub(crate) right: Option<Box<Node<C>>>,
50}
51
52impl<C: TreapMapConfig> Node<C> {
53 pub fn new(
54 key: C::SearchKey, value: C::Value, sort_key: C::SortKey,
55 weight: C::Weight, priority: u64,
56 ) -> Node<C> {
57 Node {
58 key,
59 value,
60 sort_key,
61 sum_weight: weight.clone(),
62 weight,
63 priority,
64 left: None,
65 right: None,
66 }
67 }
68
69 pub(crate) fn get(
70 &self, sort_key: &C::SortKey, key: &C::SearchKey,
71 ) -> Option<&C::Value> {
72 match C::next_node_dir((sort_key, key), (&self.sort_key, &self.key)) {
73 None => Some(&self.value),
74 Some(Direction::Left) => self.left.as_ref()?.get(sort_key, key),
75 Some(Direction::Right) => self.right.as_ref()?.get(sort_key, key),
76 }
77 }
78
79 pub(crate) fn update_inner<U: TreapNodeUpdate<C>>(
80 maybe_node: &mut Option<Box<Node<C>>>, updater: U,
81 ) -> (U::Ret, bool, bool) {
82 let next_node_dir = if let Some(node) = maybe_node {
84 C::next_node_dir(updater.treap_key(), (&node.sort_key, &node.key))
85 } else {
86 None
87 };
88
89 let (ret, update_weight, mut update_priority) = match next_node_dir {
91 None => {
92 let update_result = updater.update_node(maybe_node.as_mut());
93 Node::process_update_result::<U>(maybe_node, update_result)
94 }
95
96 Some(dir) => {
97 let node = maybe_node.as_mut().unwrap();
98 let next_node = match dir {
99 Direction::Left => &mut node.left,
100 Direction::Right => &mut node.right,
101 };
102 Node::update_inner(next_node, updater)
103 }
104 };
105
106 if let Some(node) = maybe_node.as_mut() {
108 if update_weight {
109 node.update_weight()
110 }
111 if let (Some(dir), true) = (next_node_dir, update_priority) {
112 match dir {
113 Direction::Left
114 if node.left.as_ref().map_or(false, |left| {
115 node.priority < left.priority
116 }) =>
117 {
118 node.right_rotate();
119 }
120 Direction::Right
121 if node.right.as_ref().map_or(false, |right| {
122 node.priority < right.priority
123 }) =>
124 {
125 node.left_rotate();
126 }
127 _ => {
128 update_priority = false;
129 }
130 }
131 }
132 }
133 (ret, update_weight, update_priority)
134 }
135
136 fn process_update_result<U: TreapNodeUpdate<C>>(
137 maybe_node: &mut Option<Box<Node<C>>>,
138 result: OpResult<C, U::Ret, U::DeleteRet>,
139 ) -> (U::Ret, bool, bool) {
140 match result {
141 OpResult::Noop(ret) => (ret, false, false),
142 OpResult::Updated { update_weight, ret } => {
143 (ret, update_weight, false)
144 }
145 OpResult::InsertOnVacant { insert, ret } => {
146 let _ = mem::replace(maybe_node, Some(insert));
149 (ret, true, true)
150 }
151 OpResult::Delete(delete_ret) => {
152 let deleted_node = if maybe_node.is_some() {
153 Some(Node::delete(maybe_node))
154 } else {
155 None
156 };
157 let ret = U::handle_delete(deleted_node, delete_ret);
158 (ret, true, true)
159 }
160 }
161 }
162
163 fn delete(mustbe_node: &mut Option<Box<Node<C>>>) -> Box<Self> {
165 use Direction::*;
166 let node = mustbe_node.as_mut().unwrap();
167 let next_root = match (&node.left, &node.right) {
168 (None, None) => {
169 return mem::take(mustbe_node).unwrap();
171 }
172 (None, Some(_)) => Right,
173 (Some(_), None) => Left,
174 (Some(left), Some(right)) => {
175 if left.priority < right.priority {
176 Right
177 } else {
178 Left
179 }
180 }
181 };
182
183 let res = match next_root {
184 Right => {
185 node.left_rotate();
187 Node::delete(&mut node.left)
189 }
190 Left => {
191 node.right_rotate();
193 Node::delete(&mut node.right)
195 }
196 };
197
198 node.update_weight();
199 res
200 }
201
202 fn right_rotate(self: &mut Box<Node<C>>) {
209 let y_node = self;
216 let mut x_node = mem::take(&mut y_node.left).unwrap();
217
218 mem::swap::<Box<Node<C>>>(y_node, &mut x_node);
224 let (x_node, mut y_node) = (y_node, x_node);
225
226 mem::swap::<Option<Box<Node<C>>>>(&mut x_node.right, &mut y_node.left);
231
232 y_node.update_weight();
237 x_node.right = Some(y_node);
238
239 x_node.update_weight();
246 }
247
248 fn left_rotate(self: &mut Box<Node<C>>) {
254 let x_node = self;
261 let mut y_node = mem::take(&mut x_node.right).unwrap();
262
263 mem::swap::<Box<Node<C>>>(x_node, &mut y_node);
269 let (y_node, mut x_node) = (x_node, y_node);
271
272 mem::swap::<Option<Box<Node<C>>>>(&mut y_node.left, &mut x_node.right);
277
278 x_node.update_weight();
283 y_node.left = Some(x_node);
284
285 y_node.update_weight();
292 }
293
294 pub(crate) fn update_weight(&mut self) {
295 self.sum_weight = self.weight.clone();
296 if let Some(left) = &self.left {
297 self.sum_weight.accure(&left.sum_weight);
298 }
299 if let Some(right) = &self.right {
300 self.sum_weight.accure(&right.sum_weight);
301 }
302 }
303
304 pub fn sum_weight(&self) -> C::Weight { self.sum_weight.clone() }
305
306 #[cfg(any(test, feature = "testonly_code"))]
307 pub(crate) fn assert_consistency(&self)
308 where C::Weight: Eq + std::fmt::Debug {
309 let mut weight = self.weight.clone();
310
311 if let Some(left) = self.left.as_ref() {
312 weight.accure(&left.sum_weight);
313 assert!(left.priority <= self.priority);
314 left.assert_consistency();
315 assert_eq!(
316 C::next_node_dir(
317 (&left.sort_key, &left.key),
318 (&self.sort_key, &self.key)
319 ),
320 Some(Direction::Left)
321 );
322 }
323 if let Some(right) = self.right.as_ref() {
324 weight.accure(&right.sum_weight);
325 assert!(right.priority <= self.priority);
326 right.assert_consistency();
327 assert_eq!(
328 C::next_node_dir(
329 (&right.sort_key, &right.key),
330 (&self.sort_key, &self.key)
331 ),
332 Some(Direction::Right)
333 );
334 }
335
336 assert_eq!(weight, self.sum_weight);
337 }
338}
339
340impl<C: TreapMapConfig> MallocSizeOf for Node<C>
341where
342 C::SearchKey: MallocSizeOf,
343 C::SortKey: MallocSizeOf,
344 C::Value: MallocSizeOf,
345 C::Weight: MallocSizeOf,
346{
347 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
348 self.key.size_of(ops)
349 + self.sort_key.size_of(ops)
350 + self.value.size_of(ops)
351 + self.weight.size_of(ops)
352 + self.sum_weight.size_of(ops)
353 + self.left.size_of(ops)
354 + self.right.size_of(ops)
355 }
356}