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 | 201 | pub struct NodeTree { |
|
196 | 202 | readonly: Box<dyn Deref<Target = [Block]> + Send>, |
|
203 | growable: Vec<Block>, | |
|
204 | root: Block, | |
|
197 | 205 | } |
|
198 | 206 | |
|
199 | 207 | impl Index<usize> for NodeTree { |
|
200 | 208 | type Output = Block; |
|
201 | 209 | |
|
202 | 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 | 239 | impl NodeTree { |
|
225 | fn len(&self) -> usize { | |
|
226 | self.readonly.len() | |
|
240 | /// Initiate a NodeTree from an immutable slice-like of `Block` | |
|
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 | 264 | fn is_empty(&self) -> bool { |
|
230 | self.len() == 0 | |
|
265 | false | |
|
231 | 266 | } |
|
232 | 267 | |
|
233 | 268 | /// Main working method for `NodeTree` searches |
@@ -237,9 +272,6 b' impl NodeTree {' | |||
|
237 | 272 | &self, |
|
238 | 273 | prefix: NodePrefixRef<'p>, |
|
239 | 274 | ) -> Result<Option<Revision>, NodeMapError> { |
|
240 | if self.is_empty() { | |
|
241 | return Ok(None); | |
|
242 | } | |
|
243 | 275 | let mut visit = self.len() - 1; |
|
244 | 276 | for i in 0..prefix.len() { |
|
245 | 277 | let nybble = prefix.get_nybble(i); |
@@ -255,16 +287,18 b' impl NodeTree {' | |||
|
255 | 287 | |
|
256 | 288 | impl From<Vec<Block>> for NodeTree { |
|
257 | 289 | fn from(vec: Vec<Block>) -> Self { |
|
258 | NodeTree { | |
|
259 | readonly: Box::new(vec), | |
|
260 | } | |
|
290 | Self::new(Box::new(vec)) | |
|
261 | 291 | } |
|
262 | 292 | } |
|
263 | 293 | |
|
264 | 294 | impl fmt::Debug for NodeTree { |
|
265 | 295 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
266 |
let |
|
|
267 | write!(f, "readonly: {:?}", blocks) | |
|
296 | let readonly: &[Block] = &*self.readonly; | |
|
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 | 399 | assert_eq!( |
|
366 | 400 | format!("{:?}", nt), |
|
367 | 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 | 410 | let mut idx: TestIndex = HashMap::new(); |
|
375 | 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 | 414 | assert_eq!(nt.find_hex(&idx, "1")?, Some(1)); |
|
379 | 415 | assert_eq!(nt.find_hex(&idx, "12")?, Some(1)); |
|
380 | 416 | assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1)); |
@@ -401,4 +437,25 b' mod tests {' | |||
|
401 | 437 | assert_eq!(nt.find_hex(&idx, "00"), Ok(Some(0))); |
|
402 | 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