Show More
@@ -191,16 +191,31 b' impl fmt::Debug for Block {' | |||||
191 | } |
|
191 | } | |
192 | } |
|
192 | } | |
193 |
|
193 | |||
194 | /// A 16-radix tree with the root block at the end |
|
194 | /// A mutable 16-radix tree with the root block logically at the end | |
|
195 | /// | |||
|
196 | /// Because of the append only nature of our node trees, we need to | |||
|
197 | /// keep the original untouched and store new blocks separately. | |||
|
198 | /// | |||
|
199 | /// The mutable root `Block` is kept apart so that we don't have to rebump | |||
|
200 | /// it on each insertion. | |||
195 | pub struct NodeTree { |
|
201 | pub struct NodeTree { | |
196 | readonly: Box<dyn Deref<Target = [Block]> + Send>, |
|
202 | readonly: Box<dyn Deref<Target = [Block]> + Send>, | |
|
203 | growable: Vec<Block>, | |||
|
204 | root: Block, | |||
197 | } |
|
205 | } | |
198 |
|
206 | |||
199 | impl Index<usize> for NodeTree { |
|
207 | impl Index<usize> for NodeTree { | |
200 | type Output = Block; |
|
208 | type Output = Block; | |
201 |
|
209 | |||
202 | fn index(&self, i: usize) -> &Block { |
|
210 | fn index(&self, i: usize) -> &Block { | |
203 |
|
|
211 | let ro_len = self.readonly.len(); | |
|
212 | if i < ro_len { | |||
|
213 | &self.readonly[i] | |||
|
214 | } else if i == ro_len + self.growable.len() { | |||
|
215 | &self.root | |||
|
216 | } else { | |||
|
217 | &self.growable[i - ro_len] | |||
|
218 | } | |||
204 | } |
|
219 | } | |
205 | } |
|
220 | } | |
206 |
|
221 | |||
@@ -222,12 +237,32 b" fn has_prefix_or_none<'p>(" | |||||
222 | } |
|
237 | } | |
223 |
|
238 | |||
224 | impl NodeTree { |
|
239 | impl NodeTree { | |
225 | fn len(&self) -> usize { |
|
240 | /// Initiate a NodeTree from an immutable slice-like of `Block` | |
226 | self.readonly.len() |
|
241 | /// | |
|
242 | /// We keep `readonly` and clone its root block if it isn't empty. | |||
|
243 | fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self { | |||
|
244 | let root = readonly | |||
|
245 | .last() | |||
|
246 | .map(|b| b.clone()) | |||
|
247 | .unwrap_or_else(|| Block::new()); | |||
|
248 | NodeTree { | |||
|
249 | readonly: readonly, | |||
|
250 | growable: Vec::new(), | |||
|
251 | root: root, | |||
|
252 | } | |||
227 | } |
|
253 | } | |
228 |
|
254 | |||
|
255 | /// Total number of blocks | |||
|
256 | fn len(&self) -> usize { | |||
|
257 | self.readonly.len() + self.growable.len() + 1 | |||
|
258 | } | |||
|
259 | ||||
|
260 | /// Implemented for completeness | |||
|
261 | /// | |||
|
262 | /// A `NodeTree` always has at least the mutable root block. | |||
|
263 | #[allow(dead_code)] | |||
229 | fn is_empty(&self) -> bool { |
|
264 | fn is_empty(&self) -> bool { | |
230 | self.len() == 0 |
|
265 | false | |
231 | } |
|
266 | } | |
232 |
|
267 | |||
233 | /// Main working method for `NodeTree` searches |
|
268 | /// Main working method for `NodeTree` searches | |
@@ -237,9 +272,6 b' impl NodeTree {' | |||||
237 | &self, |
|
272 | &self, | |
238 | prefix: NodePrefixRef<'p>, |
|
273 | prefix: NodePrefixRef<'p>, | |
239 | ) -> Result<Option<Revision>, NodeMapError> { |
|
274 | ) -> Result<Option<Revision>, NodeMapError> { | |
240 | if self.is_empty() { |
|
|||
241 | return Ok(None); |
|
|||
242 | } |
|
|||
243 | let mut visit = self.len() - 1; |
|
275 | let mut visit = self.len() - 1; | |
244 | for i in 0..prefix.len() { |
|
276 | for i in 0..prefix.len() { | |
245 | let nybble = prefix.get_nybble(i); |
|
277 | let nybble = prefix.get_nybble(i); | |
@@ -255,16 +287,18 b' impl NodeTree {' | |||||
255 |
|
287 | |||
256 | impl From<Vec<Block>> for NodeTree { |
|
288 | impl From<Vec<Block>> for NodeTree { | |
257 | fn from(vec: Vec<Block>) -> Self { |
|
289 | fn from(vec: Vec<Block>) -> Self { | |
258 | NodeTree { |
|
290 | Self::new(Box::new(vec)) | |
259 | readonly: Box::new(vec), |
|
|||
260 | } |
|
|||
261 | } |
|
291 | } | |
262 | } |
|
292 | } | |
263 |
|
293 | |||
264 | impl fmt::Debug for NodeTree { |
|
294 | impl fmt::Debug for NodeTree { | |
265 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
295 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
266 |
let |
|
296 | let readonly: &[Block] = &*self.readonly; | |
267 | write!(f, "readonly: {:?}", blocks) |
|
297 | write!( | |
|
298 | f, | |||
|
299 | "readonly: {:?}, growable: {:?}, root: {:?}", | |||
|
300 | readonly, self.growable, self.root | |||
|
301 | ) | |||
268 | } |
|
302 | } | |
269 | } |
|
303 | } | |
270 |
|
304 | |||
@@ -365,7 +399,9 b' mod tests {' | |||||
365 | assert_eq!( |
|
399 | assert_eq!( | |
366 | format!("{:?}", nt), |
|
400 | format!("{:?}", nt), | |
367 | "readonly: \ |
|
401 | "readonly: \ | |
368 |
[{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}] |
|
402 | [{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}], \ | |
|
403 | growable: [], \ | |||
|
404 | root: {0: Block(1), 1: Rev(1)}", | |||
369 | ); |
|
405 | ); | |
370 | } |
|
406 | } | |
371 |
|
407 | |||
@@ -374,7 +410,7 b' mod tests {' | |||||
374 | let mut idx: TestIndex = HashMap::new(); |
|
410 | let mut idx: TestIndex = HashMap::new(); | |
375 | pad_insert(&mut idx, 1, "1234deadcafe"); |
|
411 | pad_insert(&mut idx, 1, "1234deadcafe"); | |
376 |
|
412 | |||
377 |
let nt = NodeTree::from(vec![block! |
|
413 | let nt = NodeTree::from(vec![block! {1: Rev(1)}]); | |
378 | assert_eq!(nt.find_hex(&idx, "1")?, Some(1)); |
|
414 | assert_eq!(nt.find_hex(&idx, "1")?, Some(1)); | |
379 | assert_eq!(nt.find_hex(&idx, "12")?, Some(1)); |
|
415 | assert_eq!(nt.find_hex(&idx, "12")?, Some(1)); | |
380 | assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1)); |
|
416 | assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1)); | |
@@ -401,4 +437,25 b' mod tests {' | |||||
401 | assert_eq!(nt.find_hex(&idx, "00"), Ok(Some(0))); |
|
437 | assert_eq!(nt.find_hex(&idx, "00"), Ok(Some(0))); | |
402 | assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0))); |
|
438 | assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0))); | |
403 | } |
|
439 | } | |
|
440 | ||||
|
441 | #[test] | |||
|
442 | fn test_mutated_find() -> Result<(), NodeMapError> { | |||
|
443 | let mut idx = TestIndex::new(); | |||
|
444 | pad_insert(&mut idx, 9, "012"); | |||
|
445 | pad_insert(&mut idx, 0, "00a"); | |||
|
446 | pad_insert(&mut idx, 2, "cafe"); | |||
|
447 | pad_insert(&mut idx, 3, "15"); | |||
|
448 | pad_insert(&mut idx, 1, "10"); | |||
|
449 | ||||
|
450 | let nt = NodeTree { | |||
|
451 | readonly: sample_nodetree().readonly, | |||
|
452 | growable: vec![block![0: Rev(1), 5: Rev(3)]], | |||
|
453 | root: block![0: Block(1), 1:Block(3), 12: Rev(2)], | |||
|
454 | }; | |||
|
455 | assert_eq!(nt.find_hex(&idx, "10")?, Some(1)); | |||
|
456 | assert_eq!(nt.find_hex(&idx, "c")?, Some(2)); | |||
|
457 | assert_eq!(nt.find_hex(&idx, "00")?, Some(0)); | |||
|
458 | assert_eq!(nt.find_hex(&idx, "01")?, Some(9)); | |||
|
459 | Ok(()) | |||
|
460 | } | |||
404 | } |
|
461 | } |
General Comments 0
You need to be logged in to leave comments.
Login now