btree_slab/generic/node/
leaf.rs

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