1use std::cmp::Ordering;
2
3use crate::{
4 utils::{binary_search_min, Array},
5 Storage, M,
6};
7
8use super::{Balance, Offset, WouldUnderflow};
9
10#[derive(Clone)]
11pub struct Leaf<T, S: Storage<T>> {
12 parent: Option<S::Node>,
13 items: Array<T, { M + 1 }>,
14}
15
16impl<T, S: Storage<T>> Leaf<T, S> {
17 pub fn new(parent: Option<S::Node>, items: Array<T, { M + 1 }>) -> Self {
18 Self { parent, items }
19 }
20
21 #[inline]
22 pub fn from_item(parent: Option<S::Node>, item: T) -> Leaf<T, S> {
23 let mut items = Array::new();
24 items.push(item);
25
26 Leaf { parent, items }
27 }
28
29 pub fn forget(&mut self) {
31 std::mem::forget(std::mem::take(&mut self.items));
32 }
33
34 #[inline]
35 pub fn parent(&self) -> Option<S::Node> {
36 self.parent
37 }
38
39 #[inline]
40 pub fn set_parent(&mut self, p: Option<S::Node>) {
41 self.parent = p
42 }
43
44 #[inline]
45 pub fn item_count(&self) -> usize {
46 self.items.len()
47 }
48
49 #[inline]
50 pub fn items(&self) -> &Array<T, { M + 1 }> {
51 &self.items
52 }
53
54 #[inline]
55 pub fn iter(&self) -> std::slice::Iter<T> {
56 self.items.as_ref().iter()
57 }
58
59 #[inline]
60 pub fn get<Q: ?Sized>(&self, cmp: impl Fn(&T, &Q) -> Ordering, key: &Q) -> Option<&T> {
61 match binary_search_min(cmp, &self.items, key) {
62 Some((i, eq)) => {
63 if eq {
64 Some(&self.items[i])
65 } else {
66 None
67 }
68 }
69 _ => None,
70 }
71 }
72
73 #[inline]
74 pub fn get_mut<Q: ?Sized>(
75 &mut self,
76 cmp: impl Fn(&T, &Q) -> Ordering,
77 key: &Q,
78 ) -> Option<&mut T> {
79 match binary_search_min(cmp, &self.items, key) {
80 Some((i, eq)) => {
81 if eq {
82 Some(&mut self.items[i])
83 } else {
84 None
85 }
86 }
87 _ => None,
88 }
89 }
90
91 #[inline]
93 pub fn offset_of<Q: ?Sized>(
94 &self,
95 cmp: impl Fn(&T, &Q) -> Ordering,
96 key: &Q,
97 ) -> Result<Offset, Offset> {
98 match binary_search_min(cmp, &self.items, key) {
99 Some((i, eq)) => {
100 if eq {
101 Ok(i.into())
102 } else {
103 Err((i + 1).into())
104 }
105 }
106 None => Err(0.into()),
107 }
108 }
109
110 #[inline]
111 pub fn item(&self, offset: Offset) -> Option<&T> {
112 match offset.value() {
113 Some(offset) => self.items.get(offset),
114 None => None,
115 }
116 }
117
118 #[inline]
119 pub fn item_mut(&mut self, offset: Offset) -> Option<&mut T> {
120 match offset.value() {
121 Some(offset) => self.items.get_mut(offset),
122 None => None,
123 }
124 }
125
126 #[inline]
127 pub fn insert_by_key(
128 &mut self,
129 cmp: impl Fn(&T, &T) -> Ordering,
130 mut item: T,
131 ) -> (Offset, Option<T>) {
132 match binary_search_min(cmp, &self.items, &item) {
133 Some((i, eq)) => {
134 if eq {
135 std::mem::swap(&mut item, &mut self.items[i]);
136 (i.into(), Some(item))
137 } else {
138 self.items.insert(i + 1, item);
139 ((i + 1).into(), None)
140 }
141 }
142 None => {
143 self.items.insert(0, item);
144 (0.into(), None)
145 }
146 }
147 }
148
149 #[inline]
150 pub fn split(&mut self) -> (usize, T, Leaf<T, S>) {
151 assert!(self.is_overflowing());
152
153 let median_i = (self.items.len() - 1) / 2;
154
155 let right_items = self.items.drain(median_i + 1..).collect();
156 let median = self.items.pop().unwrap();
157
158 let right_leaf = Leaf {
159 parent: self.parent,
160 items: right_items,
161 };
162
163 assert!(!self.is_underflowing());
164 assert!(!right_leaf.is_underflowing());
165
166 (self.items.len(), median, right_leaf)
167 }
168
169 #[inline]
170 pub fn append(&mut self, separator: T, mut other: Leaf<T, S>) -> Offset {
171 let offset = self.items.len();
172 self.items.push(separator);
173 self.items.append(&mut other.items);
174 offset.into()
175 }
176
177 #[inline]
178 pub fn push_left(&mut self, item: T) {
179 self.items.insert(0, item)
180 }
181
182 #[inline]
183 pub fn pop_left(&mut self) -> Result<T, WouldUnderflow> {
184 if self.item_count() < M / 2 {
185 Err(WouldUnderflow)
186 } else {
187 Ok(self.items.remove(0).unwrap())
188 }
189 }
190
191 #[inline]
192 pub fn push_right(&mut self, item: T) -> Offset {
193 let offset = self.items.len();
194 self.items.push(item);
195 offset.into()
196 }
197
198 #[inline]
199 pub fn pop_right(&mut self) -> Result<(Offset, T), WouldUnderflow> {
200 if self.item_count() < M / 2 {
201 Err(WouldUnderflow)
202 } else {
203 let offset = self.items.len();
204 let item = self.items.pop().unwrap();
205 Ok((offset.into(), item))
206 }
207 }
208
209 #[inline]
210 pub fn balance(&self) -> Balance {
211 if self.is_overflowing() {
212 Balance::Overflow
213 } else if self.is_underflowing() {
214 Balance::Underflow(self.items.is_empty())
215 } else {
216 Balance::Balanced
217 }
218 }
219
220 #[inline]
221 pub fn is_overflowing(&self) -> bool {
222 self.item_count() > M
223 }
224
225 #[inline]
226 pub fn is_underflowing(&self) -> bool {
227 self.item_count() < M / 2 - 1
228 }
229
230 #[inline]
232 pub fn insert(&mut self, offset: Offset, item: T) {
233 match offset.value() {
234 Some(offset) => self.items.insert(offset, item),
235 None => panic!("Offset out of bounds"),
236 }
237 }
238
239 #[inline]
242 pub fn remove(&mut self, offset: Offset) -> T {
243 match offset.value() {
244 Some(offset) => self.items.remove(offset).unwrap(),
245 None => panic!("Offset out of bounds"),
246 }
247 }
248
249 #[inline]
250 pub fn remove_last(&mut self) -> T {
251 self.items.pop().unwrap()
252 }
253
254 #[cfg(feature = "dot")]
258 #[inline]
259 pub fn dot_write_label<W: std::io::Write>(&self, f: &mut W) -> std::io::Result<()>
260 where
261 T: std::fmt::Display,
262 {
263 for item in &self.items {
264 write!(f, "{{{}}}|", item)?;
265 }
266
267 Ok(())
268 }
269
270 #[cfg(debug_assertions)]
271 pub fn validate(
272 &self,
273 cmp: impl Fn(&T, &T) -> Ordering,
274 parent: Option<S::Node>,
275 min: Option<&T>,
276 max: Option<&T>,
277 ) {
278 if self.parent() != parent {
279 panic!("wrong parent")
280 }
281
282 if min.is_some() || max.is_some() {
283 match self.balance() {
285 Balance::Overflow => panic!("leaf is overflowing"),
286 Balance::Underflow(_) => panic!("leaf is underflowing"),
287 _ => (),
288 }
289 }
290
291 if !self.items.windows(2).all(|w| cmp(&w[0], &w[1]).is_lt()) {
292 panic!("leaf items are not sorted")
293 }
294
295 if let Some(min) = min {
296 if let Some(item) = self.items.first() {
297 if cmp(min, item).is_ge() {
298 panic!("leaf item key is greater than right separator")
299 }
300 }
301 }
302
303 if let Some(max) = max {
304 if let Some(item) = self.items.last() {
305 if cmp(max, item).is_le() {
306 panic!("leaf item key is less than left separator")
307 }
308 }
309 }
310 }
311}