diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61c0452 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +Cargo.lock +tst.dot \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 911efcb..6db6dee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,13 +3,13 @@ A Rust implementation of Ternary Search Trees, with no unsafe blocks and a simpl https://crates.io/crates/ternary-tree-wasm). [![Build Status]( http://travis-ci.com/julien-montmartin/ternary-tree.svg?branch=master)]( - http://travis-ci.com/julien-montmartin/ternary-tree) + http://travis-ci.com/julien-montmartin/ternary-tree) [![Code coverage]( http://codecov.io/gh/julien-montmartin/ternary-tree/branch/master/graph/badge.svg)]( - http://codecov.io/gh/julien-montmartin/ternary-tree) + http://codecov.io/gh/julien-montmartin/ternary-tree) [![Latest version]( http://img.shields.io/crates/v/ternary-tree.svg)]( - http://crates.io/crates/ternary-tree) + http://crates.io/crates/ternary-tree) [![API](https://docs.rs/ternary-tree/badge.svg)]( - https://docs.rs/ternary-tree/) + https://docs.rs/ternary-tree/) A Ternary Search Tree (TST) is a data structure which stores key/value pairs in a tree. The key is a string, and its characters are placed in the tree nodes. Each node may have three children (hence the name): a _left_ child, a @@ -115,16 +115,15 @@ assert_eq!(map.get("cca"), Some(&"xxx")); #![forbid(unsafe_code)] -use std::str::Chars; -use std::mem::replace; -use std::cmp::Ordering::Less; use std::cmp::Ordering::Equal; use std::cmp::Ordering::Greater; -use std::io::Write; -use std::ptr; +use std::cmp::Ordering::Less; use std::fmt; +use std::io::Write; use std::mem; - +use std::mem::replace; +use std::ptr; +use std::str::Chars; /// A `Tst` is a ternary tree structure which stores key value pairs and roughly behave like a map, but allowing /// more flexible ways to find and iterate over values. @@ -132,250 +131,359 @@ use std::mem; /// See the [module documentation]( ./index.html) for example usage and motivation. pub struct Tst { - root: Link, - count: usize } - type Link = Option>>; - struct Node { - label: char, value: Option, left: Link, middle: Link, - right: Link + right: Link, + count: usize, } +fn link_count(link: &Link) -> usize { + link.as_ref().map_or(0, |v| v.count) +} -impl Default for Node { +impl Node { + fn verify_count(&self) { + assert_eq!( + self.count, + link_count(&self.left) + + link_count(&self.middle) + + link_count(&self.right) + + (if self.value.is_some() { 1 } else { 0 }) + ); + } + fn verify_balance(&self) { + assert!(!needs_rebuild(self.count, link_count(&self.left))); + assert!(!needs_rebuild(self.count, link_count(&self.right))); + } +} +impl Default for Node { fn default() -> Node { - Node { - label: '\0', value: None, left: None, middle: None, - right: None + right: None, + count: 0, } } } - impl fmt::Debug for Node { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - - let value_box = match self.value { - - None => "☐", Some(_) => "☑" - }; + let value_box = match self.value { + None => "☐", + Some(_) => "☑", + }; write!(f, "{}-{}", value_box, self.label) } } +fn verify_r(link: &Link) { + match link { + None => {} + Some(ref node) => { + node.verify_count(); + node.verify_balance(); + verify_r(&node.left); + verify_r(&node.right); + verify_r(&node.middle); + } + } +} -fn insert_r(link: &mut Link, label: char, mut key_tail: Chars, value: T) -> Option { - - let choose_branch_and_do_insert = |node: &mut Box>| match label.cmp(&node.label) { - - Less => insert_r(&mut node.left, label, key_tail, value), - - Greater => insert_r(&mut node.right, label, key_tail, value), - - Equal => { - - let new_label = key_tail.next(); - - match new_label { - - None => replace(&mut node.value, Some(value)), - - Some(label) => insert_r(&mut node.middle, label, key_tail, value) +fn flatten_r(link: &mut Link, nodes_in_order: &mut Vec>) { + match link { + None => {} + Some(_) => { + let mut me = replace(link, None); + let ref mut node = me.as_mut().unwrap(); + let mut left = replace(&mut node.left, None); + let mut right = replace(&mut node.right, None); + node.count -= link_count(&left); + node.count -= link_count(&right); + flatten_r(&mut left, nodes_in_order); + assert_eq!( + 0 < node.count, + node.value.is_some() || node.middle.is_some() + ); + if 0 < node.count { + //pruning + nodes_in_order.push(me); } + flatten_r(&mut right, nodes_in_order); + } + } +} +fn build(nodes_in_order: &mut [Link], start: usize, prefix_sums: &[usize]) -> Link { + assert_eq!(nodes_in_order.len(), prefix_sums.len()); + if nodes_in_order.is_empty() { + return None; + } + let end = prefix_sums.last().unwrap_or(&0); + let center = (start + end) >> 1; + // if the sizes are [1,1,1], then end==3, center = 1 (well, 1.5), + // the prefix_sums: [1,2,3], and we want to find the prefix_sums[i-1]<=center(link: &mut Link) { + let mut nodes_in_order = vec![]; + flatten_r(link, &mut nodes_in_order); + let mut prefix_sum_of_sizes = vec![]; + for ref node in nodes_in_order.iter() { + prefix_sum_of_sizes.push(link_count(node) + prefix_sum_of_sizes.last().unwrap_or(&0)); + } + *link = build(&mut nodes_in_order, 0, &prefix_sum_of_sizes); +} +fn needs_rebuild(total: usize, child: usize) -> bool { + // needs_rebuild(0,0) must be true + return total * 3 <= child * 4; +} +fn insert_r( + link: &mut Link, + label: char, + mut key_tail: Chars, + value: T, + rebuild_allowed: bool, +) -> Option { + if link.is_none() { + *link = Some(Box::new(Node:: { + label, + ..Default::default() + })); + } + let ref mut node = link.as_mut().unwrap(); + let rebuild_on_new; + let old_value = if label == node.label { + rebuild_on_new = false; + match key_tail.next() { + None => replace(&mut node.value, Some(value)), + Some(label) => insert_r(&mut node.middle, label, key_tail, value, true), } + } else { + let child = if label < node.label { + &mut node.left + } else { + &mut node.right + }; + rebuild_on_new = rebuild_allowed && needs_rebuild(node.count + 1, link_count(child) + 1); + insert_r( + child, + label, + key_tail, + value, + rebuild_allowed && !rebuild_on_new, + ) }; - - match link { - - None => { - - let mut node = Box::new(Node::{label, .. Default::default()}); - - let old_value = choose_branch_and_do_insert(&mut node); - - *link = Some(node); - - old_value + if old_value.is_none() { + node.count += 1; + node.verify_count(); + if rebuild_on_new { + rebuild(link); } - - Some(ref mut node) => choose_branch_and_do_insert(node) } + old_value } - fn get_r<'a, T>(link: &'a Link, label: char, key_tail: &mut Chars) -> Option<&'a T> { - match *link { - None => None, Some(ref node) => match label.cmp(&node.label) { - Less => get_r(&node.left, label, key_tail), Equal => { - let new_label = key_tail.next(); match new_label { - None => match node.value { - None => None, - Some(ref value) => Some(value) - } + Some(ref value) => Some(value), + }, - Some(label) => get_r(&node.middle, label, key_tail) + Some(label) => get_r(&node.middle, label, key_tail), } - }, + } Greater => get_r(&node.right, label, key_tail), - } + }, } } +fn get_nth_r<'a, T>(link: &'a Link, mut n: usize, mut path: String) -> Option<(String, &'a T)> { + match *link { + None => None, + Some(ref node) => { + let left_count = link_count(&node.left); + if n < left_count { + return get_nth_r(&node.left, n, path); + } + n -= left_count; + if node.value.is_some() { + if n == 0 { + path.push(node.label); + return Some((path, node.value.as_ref().unwrap())); + } else { + n -= 1; + } + } + let middle_count = link_count(&node.middle); + if n < middle_count { + path.push(node.label); + return get_nth_r(&node.middle, n, path); + } + n -= middle_count; + get_nth_r(&node.right, n, path) + } + } +} fn get_r_mut<'a, T>(link: &'a mut Link, label: char, key_tail: &mut Chars) -> Option<&'a mut T> { - match *link { - None => None, Some(ref mut node) => match label.cmp(&node.label) { - Less => get_r_mut(&mut node.left, label, key_tail), Equal => { - let new_label = key_tail.next(); match new_label { - None => match node.value { - None => None, - Some(ref mut value) => Some(value) - } + Some(ref mut value) => Some(value), + }, - Some(label) => get_r_mut(&mut node.middle, label, key_tail) + Some(label) => get_r_mut(&mut node.middle, label, key_tail), } - }, + } Greater => get_r_mut(&mut node.right, label, key_tail), - } + }, } } - -fn remove_r(link: &mut Link, label: char, key_tail: &mut Chars) -> (bool, Option) { - +fn remove_r( + link: &mut Link, + label: char, + key_tail: &mut Chars, + rebuild_allowed: bool, +) -> Option { match *link { - - None => (false, None), - - Some(ref mut node) => match label.cmp(&node.label) { - - Less => { - - let (prune, old_value) = remove_r(&mut node.left, label, key_tail); - - if prune { - - node.left = None; + None => None, + Some(ref mut node) => { + assert!(0 < node.count); + let rebuild_on_removal; + let removed = match label.cmp(&node.label) { + Less => { + rebuild_on_removal = + rebuild_allowed && needs_rebuild(node.count - 1, link_count(&node.right)); + remove_r( + &mut node.left, + label, + key_tail, + rebuild_allowed && !rebuild_on_removal, + ) } - - let more_pruning = node.value.is_none() && node.left.is_none() && node.middle.is_none() && node.right.is_none(); - (more_pruning, old_value) - } - - Equal => { - - let new_label = key_tail.next(); - - match new_label { - - None => { - - let old_value = replace(&mut node.value, None); - - let prune = old_value.is_some() && node.left.is_none() && node.middle.is_none() && node.right.is_none(); - (prune, old_value) - } - - Some(label) => { - - let (prune, old_value) = remove_r(&mut node.middle, label, key_tail); - - if prune { - - node.middle = None; - } - - let more_pruning = node.value.is_none() && node.left.is_none() && node.middle.is_none() && node.right.is_none(); - (more_pruning, old_value) + Greater => { + rebuild_on_removal = + rebuild_allowed && needs_rebuild(node.count - 1, link_count(&node.left)); + remove_r( + &mut node.right, + label, + key_tail, + rebuild_allowed && !rebuild_on_removal, + ) + } + Equal => { + rebuild_on_removal = rebuild_allowed + && needs_rebuild( + node.count - 1, + std::cmp::max(link_count(&node.right), link_count(&node.left)), + ); + match key_tail.next() { + None => replace(&mut node.value, None), + Some(label) => remove_r(&mut node.middle, label, key_tail, true), } + // Node is only needed for as long as it is part of some key: + // node.value.is_none() && node.middle.is_none() + // We could handle the easy cases, where left or right is None, by lifting the other child. + // We might be tempted to handle the case where both are Some, by replacing us with leftmost ancestor of right, but + // that could actually destroy the balance along the path to it. + // However, we do not actually need to do anything at all here! + // All the heavy lifting is done by rebuild() when needs_rebuild() says it is necessary. + // If left & right are balanced, then our node is still helpful in providing a comparison which reduces range by 25%. + // If any of them is missing, and middle&value are empty, then needs_rebuild(0+|kid|,|kid|) will return true. + // If both kids are missing already then needs_rebuild(0,0) should return true as well. } - } - - Greater => { - - let (prune, old_value) = remove_r(&mut node.right, label, key_tail); - - if prune { - - node.right = None; + }; + if removed.is_some() { + node.count -= 1; + node.verify_count(); + if rebuild_on_removal { + rebuild(link) } - - let more_pruning = node.value.is_none() && node.left.is_none() && node.middle.is_none() && node.right.is_none(); - (more_pruning, old_value) } + removed } } } - /// How nodes are distributed. See [Stats]( ./struct.Stats.html) for a brief description. -#[derive(Default,PartialEq,Debug)] -pub struct DistStat { pub matches: usize, pub sides: usize, pub depth: usize } - +#[derive(Default, PartialEq, Debug)] +pub struct DistStat { + pub matches: usize, + pub sides: usize, + pub depth: usize, +} /// How long are the keys. See [Stats]( ./struct.Stats.html) for a brief description. -#[derive(Default,PartialEq,Debug)] -pub struct KeyLenStat { pub min: usize, pub max: usize } - +#[derive(Default, PartialEq, Debug)] +pub struct KeyLenStat { + pub min: usize, + pub max: usize, +} /// How many nodes and values are in the tree. See [Stats]( ./struct.Stats.html) for a brief description. -#[derive(Default,PartialEq,Debug)] -pub struct CountStat { pub nodes:usize, pub values: usize } - +#[derive(Default, PartialEq, Debug)] +pub struct CountStat { + pub nodes: usize, + pub values: usize, +} /// Memory used by the tree. See [Stats]( ./struct.Stats.html) for a brief description. -#[derive(Default,PartialEq,Debug)] -pub struct BytesStat { pub node: usize, pub total: usize } - +#[derive(Default, PartialEq, Debug)] +pub struct BytesStat { + pub node: usize, + pub total: usize, +} /// Contains various metrics describing the tree: its nodes, keys and values. Mostly used for tuning and debugging /// purpose. @@ -392,133 +500,117 @@ pub struct BytesStat { pub node: usize, pub total: usize } /// this value) /// * `bytes.total` total number of bytes allocated for nodes (`count.nodes` * `bytes.node`) -#[derive(Default,PartialEq,Debug)] +#[derive(Default, PartialEq, Debug)] pub struct Stats { - pub dist: Vec, pub key_len: KeyLenStat, pub count: CountStat, pub bytes: BytesStat, } - fn stat_r(stats: Stats, link: &Link, matches: usize, sides: usize, depth: usize) -> Stats { - match *link { - None => stats, Some(ref node) => { + let mut stats = stat_r(stats, &node.left, matches, sides + 1, depth + 1); - let mut stats = stat_r(stats, &node.left, matches, sides+1, depth+1); - - stats.count.nodes+=1; + stats.count.nodes += 1; if node.value.is_some() { - let matches = matches + 1; let depth = depth + 1; while stats.dist.len() <= depth { - - stats.dist.push(DistStat { matches: 0, sides: 0, depth: 0 }); + stats.dist.push(DistStat { + matches: 0, + sides: 0, + depth: 0, + }); } - stats.dist[matches].matches+=1; - stats.dist[sides].sides+=1; - stats.dist[depth].depth+=1; + stats.dist[matches].matches += 1; + stats.dist[sides].sides += 1; + stats.dist[depth].depth += 1; if stats.key_len.min == 0 || matches < stats.key_len.min { - stats.key_len.min = matches; } if matches > stats.key_len.max { - stats.key_len.max = matches; } - stats.count.values+=1; + stats.count.values += 1; } - let stats = stat_r(stats, &node.middle, matches+1, sides, depth+1); - let stats = stat_r(stats, &node.right, matches, sides+1, depth+1); + let stats = stat_r(stats, &node.middle, matches + 1, sides, depth + 1); + let stats = stat_r(stats, &node.right, matches, sides + 1, depth + 1); stats } } } - fn find_complete_root_r<'a, T>(link: &'a Link, label: char, mut key_tail: Chars) -> &'a Link { - match *link { - None => &link, Some(ref node) => match label.cmp(&node.label) { - Less => find_complete_root_r(&node.left, label, key_tail), Greater => find_complete_root_r(&node.right, label, key_tail), Equal => { - let new_label = key_tail.next(); match new_label { - None => &node.middle, - Some(label) => find_complete_root_r(&node.middle, label, key_tail) + Some(label) => find_complete_root_r(&node.middle, label, key_tail), } } - } + }, } } - -fn find_complete_root_r_mut<'a, T>(link: &'a mut Link, label: char, mut key_tail: Chars) -> &'a mut Link { - +fn find_complete_root_r_mut<'a, T>( + link: &'a mut Link, + label: char, + mut key_tail: Chars, +) -> &'a mut Link { match *link { - - None => { link } + None => link, Some(ref mut node) => match label.cmp(&node.label) { - Less => find_complete_root_r_mut(&mut node.left, label, key_tail), Greater => find_complete_root_r_mut(&mut node.right, label, key_tail), Equal => { - let new_label = key_tail.next(); match new_label { - None => &mut node.middle, - Some(label) => find_complete_root_r_mut(&mut node.middle, label, key_tail) + Some(label) => find_complete_root_r_mut(&mut node.middle, label, key_tail), } } - } + }, } } - fn visit_values_r(link: &Link, callback: &mut C) -where C: FnMut (&T) { - +where + C: FnMut(&T), +{ match *link { - None => return, Some(ref node) => { - visit_values_r(&node.left, callback); if let Some(ref value) = node.value { - callback(value); } @@ -528,20 +620,17 @@ where C: FnMut (&T) { } } - fn visit_values_r_mut(link: &mut Link, callback: &mut C) -where C: FnMut (&mut T) { - +where + C: FnMut(&mut T), +{ match *link { - None => return, Some(ref mut node) => { - visit_values_r_mut(&mut node.left, callback); if let Some(ref mut value) = node.value { - callback(value); } @@ -551,20 +640,17 @@ where C: FnMut (&mut T) { } } - fn visit_complete_values_r(link: &Link, callback: &mut C) -where C: FnMut (&T) { - +where + C: FnMut(&T), +{ match *link { - None => return, Some(ref node) => { - visit_values_r(&node.left, callback); if let Some(ref value) = node.value { - callback(value); } @@ -574,20 +660,17 @@ where C: FnMut (&T) { } } - fn visit_complete_values_r_mut(link: &mut Link, callback: &mut C) -where C: FnMut (&mut T) { - +where + C: FnMut(&mut T), +{ match *link { - None => return, Some(ref mut node) => { - visit_values_r_mut(&mut node.left, callback); if let Some(ref mut value) = node.value { - callback(value); } @@ -597,55 +680,70 @@ where C: FnMut (&mut T) { } } - -fn visit_neighbor_values_r<'a, T, C>(link: &'a Link, label: Option, key_tail: &mut Chars, tail_len: usize, range: usize, callback: &mut C) -where C: FnMut (&T) { - +fn visit_neighbor_values_r<'a, T, C>( + link: &'a Link, + label: Option, + key_tail: &mut Chars, + tail_len: usize, + range: usize, + callback: &mut C, +) where + C: FnMut(&T), +{ if range == 0 { - if let Some(label) = label { - if let Some(value) = get_r(link, label, key_tail) { - callback(value); } } - } else { - if let Some(ref node) = *link { - visit_neighbor_values_r(&node.left, label, key_tail, tail_len, range, callback); if let Some(ref value) = node.value { - let new_range = match label { + None => range - 1, - None => range-1, - - Some(label) => if label==node.label { range } else { range-1 } + Some(label) => { + if label == node.label { + range + } else { + range - 1 + } + } }; if tail_len <= new_range { - callback(value); } } { let new_range = match label { + None => range - 1, - None => range-1, - - Some(label) => if label==node.label { range } else { range-1 } + Some(label) => { + if label == node.label { + range + } else { + range - 1 + } + } }; let mut new_tail = key_tail.clone(); let new_label = new_tail.next(); - let new_len = if tail_len > 0 { tail_len-1 } else { tail_len }; + let new_len = if tail_len > 0 { tail_len - 1 } else { tail_len }; - visit_neighbor_values_r(&node.middle, new_label, &mut new_tail, new_len, new_range, callback); + visit_neighbor_values_r( + &node.middle, + new_label, + &mut new_tail, + new_len, + new_range, + callback, + ); } visit_neighbor_values_r(&node.right, label, key_tail, tail_len, range, callback); @@ -653,186 +751,226 @@ where C: FnMut (&T) { } } - -fn visit_neighbor_values_r_mut<'a, T, C>(link: &'a mut Link, label: Option, key_tail: &mut Chars, tail_len: usize, range: usize, callback: &mut C) -where C: FnMut (&mut T) { - +fn visit_neighbor_values_r_mut<'a, T, C>( + link: &'a mut Link, + label: Option, + key_tail: &mut Chars, + tail_len: usize, + range: usize, + callback: &mut C, +) where + C: FnMut(&mut T), +{ if range == 0 { - if let Some(label) = label { - if let Some(value) = get_r_mut(link, label, key_tail) { - callback(value); } } - } else { - if let Some(ref mut node) = *link { - let label_tmp = node.label; visit_neighbor_values_r_mut(&mut node.left, label, key_tail, tail_len, range, callback); if let Some(ref mut value) = node.value { - let new_range = match label { + None => range - 1, - None => range-1, - - Some(label) => if label == label_tmp { range } else { range-1 } + Some(label) => { + if label == label_tmp { + range + } else { + range - 1 + } + } }; if tail_len <= new_range { - callback(value); } } { let new_range = match label { + None => range - 1, - None => range-1, - - Some(label) => if label == node.label { range } else { range-1 } + Some(label) => { + if label == node.label { + range + } else { + range - 1 + } + } }; let mut new_tail = key_tail.clone(); let new_label = new_tail.next(); - let new_len = if tail_len > 0 { tail_len-1 } else { tail_len }; + let new_len = if tail_len > 0 { tail_len - 1 } else { tail_len }; - visit_neighbor_values_r_mut(&mut node.middle, new_label, &mut new_tail, new_len, new_range, callback); + visit_neighbor_values_r_mut( + &mut node.middle, + new_label, + &mut new_tail, + new_len, + new_range, + callback, + ); } - visit_neighbor_values_r_mut(&mut node.right, label, key_tail, tail_len, range, callback); + visit_neighbor_values_r_mut( + &mut node.right, + label, + key_tail, + tail_len, + range, + callback, + ); } } } - -fn visit_crossword_values_r<'a, T, C>(link: &'a Link, label: char, key_tail: &mut Chars, joker: char, callback: &mut C) - where C: FnMut (&T) { - +fn visit_crossword_values_r<'a, T, C>( + link: &'a Link, + label: char, + key_tail: &mut Chars, + joker: char, + callback: &mut C, +) where + C: FnMut(&T), +{ match *link { - None => return, Some(ref node) => { - if label == joker || label < node.label { - visit_crossword_values_r(&node.left, label, key_tail, joker, callback); } if label == joker || label == node.label { - let mut new_tail = key_tail.clone(); let new_label = new_tail.next(); match new_label { + None => { + if let Some(ref value) = node.value { + callback(value); + } + } - None => if let Some(ref value) = node.value { - - callback(value); - }, - - Some(label) => visit_crossword_values_r(&node.middle, label, &mut new_tail, joker, callback) + Some(label) => visit_crossword_values_r( + &node.middle, + label, + &mut new_tail, + joker, + callback, + ), } } if label == joker || label > node.label { - visit_crossword_values_r(&node.right, label, key_tail, joker, callback); } } } } - -fn visit_crossword_values_r_mut<'a, T, C>(link: &'a mut Link, label: char, key_tail: &mut Chars, joker: char, callback: &mut C) - where C: FnMut (&mut T) { - +fn visit_crossword_values_r_mut<'a, T, C>( + link: &'a mut Link, + label: char, + key_tail: &mut Chars, + joker: char, + callback: &mut C, +) where + C: FnMut(&mut T), +{ match *link { - None => return, Some(ref mut node) => { - if label == joker || label < node.label { - visit_crossword_values_r_mut(&mut node.left, label, key_tail, joker, callback); } if label == joker || label == node.label { - let mut new_tail = key_tail.clone(); let new_label = new_tail.next(); match new_label { + None => { + if let Some(ref mut value) = node.value { + callback(value); + } + } - None => if let Some(ref mut value) = node.value { - - callback(value); - }, - - Some(label) => visit_crossword_values_r_mut(&mut node.middle, label, &mut new_tail, joker, callback) + Some(label) => visit_crossword_values_r_mut( + &mut node.middle, + label, + &mut new_tail, + joker, + callback, + ), } } if label == joker || label > node.label { - visit_crossword_values_r_mut(&mut node.right, label, key_tail, joker, callback); } } } } - fn pretty_print_r<'a, T>(link: &'a Link, ids: &mut Tst, writer: &mut dyn Write) { - match *link { - None => return, Some(ref node) => { - let value_box = match node.value { - - None => "☐", Some(_) => "☑" + None => "☐", + Some(_) => "☑", }; { let mut get_id = |node: &Box>| { - let node_addr = format!("{:p}", node); let prev_id = match ids.get(&node_addr) { - None => None, - Some(id) => Some(*id) + Some(id) => Some(*id), }; match prev_id { - None => { - let id = ids.len(); ids.insert(&node_addr, id); id } - Some(id) => id + Some(id) => id, } }; - let _ = writeln!(writer, r#"N{} [label=<
{} {}
>]"#, get_id(node), value_box, node.label); - - let mut print_edge = |link, start, style| if let &Some(ref child) = link { - - let _ = writeln!(writer, r#"N{}:{} -> N{} [style={}]"#, get_id(node), start, get_id(child), style); + let _ = writeln!( + writer, + r#"N{} [label=<
{} {}
>]"#, + get_id(node), + value_box, + node.label + ); + + let mut print_edge = |link, start, style| { + if let &Some(ref child) = link { + let _ = writeln!( + writer, + r#"N{}:{} -> N{} [style={}]"#, + get_id(node), + start, + get_id(child), + style + ); + } }; print_edge(&node.left, "l", "solid"); @@ -847,9 +985,7 @@ fn pretty_print_r<'a, T>(link: &'a Link, ids: &mut Tst, writer: &mut d } } - impl Tst { - /// Create a new, empty `Tst`. The key is always a string slice and one needs only to provide a value /// type. The following code creates an empty tree which stores `bool` values /// @@ -868,11 +1004,9 @@ impl Tst { /// And the exact value type is properly guessed. pub fn new() -> Self { - - Tst { root: None, count: 0 } + Tst { root: None } } - /// Inserts `key` and `value` pair in the tree, returning any value previously associated with `key`. /// /// ``` @@ -903,28 +1037,15 @@ impl Tst { /// insertion is done, `key` is given back to the caller. pub fn insert(&mut self, key: &str, value: T) -> Option { - let mut key_tail = key.chars(); match key_tail.next() { - None => Some(value), - Some(label) => { - - let old_value = insert_r(&mut self.root, label, key_tail, value); - - if old_value.is_none() { - - self.count += 1; - } - - old_value - } + Some(label) => insert_r(&mut self.root, label, key_tail, value, true), } } - /// Returns an immutable reference to the value associated with `key`, or None. /// /// ``` @@ -936,17 +1057,18 @@ impl Tst { /// assert_eq!(v, Some(&"🍄🍄")); pub fn get(&self, key: &str) -> Option<&T> { - let mut key_tail = key.chars(); match key_tail.next() { - None => None, - Some(label) => get_r(&self.root, label, &mut key_tail) + Some(label) => get_r(&self.root, label, &mut key_tail), } } + pub fn get_nth(&self, n: usize) -> Option<(String, &T)> { + get_nth_r(&self.root, n, String::new()) + } /// Returns an mutable reference to the value associated with `key`, or `None`. /// @@ -963,18 +1085,15 @@ impl Tst { /// assert_eq!(v, Some(&"🍄🍄".to_string())); pub fn get_mut(&mut self, key: &str) -> Option<&mut T> { - let mut key_tail = key.chars(); match key_tail.next() { - None => None, - Some(label) => get_r_mut(&mut self.root, label, &mut key_tail) + Some(label) => get_r_mut(&mut self.root, label, &mut key_tail), } } - /// Removes the value associated with `key` from the tree, and returns it. Does nothing if no value is /// associated with `key`, and returns `None`. /// @@ -990,30 +1109,15 @@ impl Tst { /// assert_eq!(v, None); pub fn remove(&mut self, key: &str) -> Option { - let mut key_tail = key.chars(); - let (prune, old_value) = match key_tail.next() { - - None => (false, None), - - Some(label) => remove_r(&mut self.root, label, &mut key_tail) - }; - - if prune { - - self.root = None; - } - - if old_value.is_some() { + match key_tail.next() { + None => None, - self.count -= 1; + Some(label) => remove_r(&mut self.root, label, &mut key_tail, true), } - - old_value } - /// Returns the number of values stored in the tree. /// /// ``` @@ -1026,11 +1130,9 @@ impl Tst { /// ``` pub fn len(&self) -> usize { - - self.count + link_count(&self.root) } - /// Walks the tree, gathers various metrics about nodes, keys and values, and returns a [`Stats`]( /// ./struct.Stats.html) structure to sum it up. /// @@ -1049,18 +1151,16 @@ impl Tst { /// See [Stats]( ./struct.Stats.html) for a detailed description of available fields. pub fn stat(&self) -> Stats { - let empty_stats: Stats = Default::default(); let mut stats = stat_r(empty_stats, &self.root, 0, 0, 0); stats.bytes.node = mem::size_of::>(); - stats.bytes.total = mem::size_of::>()+stats.count.nodes*stats.bytes.node; + stats.bytes.total = mem::size_of::>() + stats.count.nodes * stats.bytes.node; stats } - /// Deletes every node and value stored in the tree. /// /// ``` @@ -1075,12 +1175,9 @@ impl Tst { /// assert_eq!(map.len(), 0); pub fn clear(&mut self) { - self.root = None; - self.count = 0; } - /// Recursively walks the tree and calls `callback` closure on each immutable value. Values are found in /// alphabetical order of keys. See also the [`iter`]( ./struct.Tst.html#method.iter) method which produces the /// same sequence of values in a non-recursive way. @@ -1096,23 +1193,23 @@ impl Tst { /// ``` pub fn visit_values(&self, mut callback: C) - where C: FnMut (&T) { - + where + C: FnMut(&T), + { visit_values_r(&self.root, &mut callback); } - /// Recursively walks the tree and calls `callback` closure on each mutable value. The same as /// [`visit_values`]( ./struct.Tst.html#method.visit_values), except the `_mut` version works on mutable /// values, and does not have an iterator counterpart. pub fn visit_values_mut(&mut self, mut callback: C) - where C: FnMut (&mut T) { - + where + C: FnMut(&mut T), + { visit_values_r_mut(&mut self.root, &mut callback); } - /// Recursively walks the tree and calls `callback` closure on each immutable value whose key begins with /// `key_prefix`. Values are found in alphabetical order of keys. See also the [`iter_complete`]( /// ./struct.Tst.html#method.iter_complete) method which produces the same sequence of values in a @@ -1144,45 +1241,41 @@ impl Tst { /// ./struct.Tst.html#method.visit_values), and all values stored in the tree are found. pub fn visit_complete_values(&self, key_prefix: &str, mut callback: C) - where C: FnMut (&T) { - + where + C: FnMut(&T), + { let mut prefix_tail = key_prefix.chars(); match prefix_tail.next() { - None => visit_values_r(&self.root, &mut callback), Some(label) => { - let new_root = find_complete_root_r(&self.root, label, prefix_tail); visit_complete_values_r(new_root, &mut callback) } } } - /// Recursively walks the tree and calls `callback` closure on each mutable value whose key begins with /// `key_prefix`. The same as [`visit_complete_values`]( ./struct.Tst.html#method.visit_complete_values), /// except the `_mut` version works on mutable values, and does not have an iterator counterpart. pub fn visit_complete_values_mut(&mut self, key_prefix: &str, mut callback: C) - where C: FnMut (&mut T) { - + where + C: FnMut(&mut T), + { let mut prefix_tail = key_prefix.chars(); match prefix_tail.next() { - None => visit_values_r_mut(&mut self.root, &mut callback), Some(label) => { - let mut new_root = find_complete_root_r_mut(&mut self.root, label, prefix_tail); visit_complete_values_r_mut(&mut new_root, &mut callback) } } } - /// Recursively walks the tree and calls `callback` closure on each immutable value whose key is _close_ to /// `key`. A key is considered _close_ to `key` within a [Hamming distance]( /// http://en.wikipedia.org/wiki/Hamming_distance) of `range` from `key`. Values are found in alphabetical @@ -1214,34 +1307,48 @@ impl Tst { /// ``` pub fn visit_neighbor_values(&self, key: &str, range: usize, mut callback: C) - where C: FnMut (&T) { - + where + C: FnMut(&T), + { let mut key_tail = key.chars(); let key_len = key.chars().count(); let label = key_tail.next(); - let tail_len = if key_len == 0 { 0 } else { key_len-1 }; - - visit_neighbor_values_r(&self.root, label, &mut key_tail, tail_len, range, &mut callback); + let tail_len = if key_len == 0 { 0 } else { key_len - 1 }; + + visit_neighbor_values_r( + &self.root, + label, + &mut key_tail, + tail_len, + range, + &mut callback, + ); } - /// Recursively walks the tree and calls `callback` closure on each mutable value whose key is _close_ to `key` /// ([Hamming distance]( http://en.wikipedia.org/wiki/Hamming_distance) of `range`). The same as /// [`visit_neighbor_values`]( ./struct.Tst.html#method.visit_neighbor_values), except the `_mut` version works /// on mutable values, and does not have an iterator counterpart. pub fn visit_neighbor_values_mut(&mut self, key: &str, range: usize, mut callback: C) - where C: FnMut (&mut T) { - + where + C: FnMut(&mut T), + { let mut key_tail = key.chars(); let key_len = key.chars().count(); let label = key_tail.next(); - let tail_len = if key_len == 0 { 0 } else { key_len-1 }; - - visit_neighbor_values_r_mut(&mut self.root, label, &mut key_tail, tail_len, range, &mut callback); + let tail_len = if key_len == 0 { 0 } else { key_len - 1 }; + + visit_neighbor_values_r_mut( + &mut self.root, + label, + &mut key_tail, + tail_len, + range, + &mut callback, + ); } - /// Recursively walks the tree and calls `callback` closure on each immutable value whose key _matches_ /// `pattern`. The `pattern` is a string slice where each `joker` character stands for _any_ character. Values /// are found in alphabetical order of keys. See also the [`iter_crossword`]( @@ -1273,45 +1380,50 @@ impl Tst { /// An empty `pattern` is meaningless, and does not find any value. pub fn visit_crossword_values(&self, pattern: &str, joker: char, mut callback: C) - where C: FnMut (&T) { - + where + C: FnMut(&T), + { let mut pattern_tail = pattern.chars(); match pattern_tail.next() { - None => return, - Some(label) => visit_crossword_values_r(&self.root, label, &mut pattern_tail, joker, &mut callback) + Some(label) => { + visit_crossword_values_r(&self.root, label, &mut pattern_tail, joker, &mut callback) + } } } - /// Recursively walks the tree and calls `callback` closure on each mutable value whose key _matches_ `pattern` /// with `joker` characters. The same as [`visit_crossword_values`]( /// ./struct.Tst.html#method.visit_crossword_values), except the `_mut` version works on mutable values, and /// does not have an iterator counterpart. pub fn visit_crossword_values_mut(&mut self, pattern: &str, joker: char, mut callback: C) - where C: FnMut (&mut T) { - + where + C: FnMut(&mut T), + { let mut pattern_tail = pattern.chars(); match pattern_tail.next() { - None => return, - Some(label) => visit_crossword_values_r_mut(&mut self.root, label, &mut pattern_tail, joker, &mut callback) + Some(label) => visit_crossword_values_r_mut( + &mut self.root, + label, + &mut pattern_tail, + joker, + &mut callback, + ), } } - /// Dump the tree in `writer` using the _dot_ language of [Graphviz]( http://www.graphviz.org) tools. A checked /// box "☑" denotes a node which stores a value (it corresponds to the last character of a key). An empty box /// "☐" means that the node has no value. Mostly used for documentation and debugging purpose. See the [module /// documentation]( ./index.html) for an example. pub fn pretty_print(&self, writer: &mut dyn Write) { - let _ = writeln!(writer, "digraph {{"); let _ = writeln!(writer, "node [shape=plaintext]"); @@ -1322,7 +1434,6 @@ impl Tst { let _ = writeln!(writer, "}}"); } - /// Create a [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values of the tree. Values are immutable, and are found in alphabetical order of /// keys by [`next`]( ./struct.TstIterator.html#method.next), and in the opposite order by [`next_back`]( @@ -1351,11 +1462,9 @@ impl Tst { /// ``` pub fn iter(&self) -> TstIterator { - TstIterator::::new(&self) } - /// Create a [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key begins with `prefix`. Values are immutable, and are found in /// alphabetical order of keys by [`next`]( ./struct.TstCompleteIterator.html#method.next), and in the opposite @@ -1385,11 +1494,9 @@ impl Tst { /// ``` pub fn iter_complete(&self, prefix: &str) -> TstCompleteIterator { - TstCompleteIterator::::new(&self, prefix) } - /// Create a [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key is _close_ to `key`. A key is considered _close_ to `key` within /// a [Hamming distance]( http://en.wikipedia.org/wiki/Hamming_distance) of `range` from `key`. An empty `key` @@ -1421,12 +1528,14 @@ impl Tst { /// assert_eq!((last_key, last_value), ("baz".to_string(), Some(&"㵅"))); /// ``` - pub fn iter_neighbor<'a, 'b>(&'a self, key: &'b str, range: usize) -> TstNeighborIterator<'a, 'b, T> { - + pub fn iter_neighbor<'a, 'b>( + &'a self, + key: &'b str, + range: usize, + ) -> TstNeighborIterator<'a, 'b, T> { TstNeighborIterator::::new(&self, key, range) } - /// Create a [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key _matches_ `pattern`. The `pattern` is a string slice where each /// `joker` character stands for _any_ character. A `pattern` of _n_ `joker` characters will find all values @@ -1457,12 +1566,18 @@ impl Tst { /// assert_eq!((last_key, last_value), ("baz".to_string(), Some(&"㵅"))); /// ``` - pub fn iter_crossword<'a, 'b>(&'a self, pattern: &'b str, joker: char) -> TstCrosswordIterator<'a, 'b, T> { - + pub fn iter_crossword<'a, 'b>( + &'a self, + pattern: &'b str, + joker: char, + ) -> TstCrosswordIterator<'a, 'b, T> { TstCrosswordIterator::::new(&self, pattern, joker) } -} + pub fn verify(&self) { + verify_r(&self.root); + } +} /// A shortcut macro to help create a small tree with a list of known `"key" => value` pairs. Calls [`insert`]( /// ./struct.Tst.html#method.insert) on each pair, in order. @@ -1494,74 +1609,59 @@ macro_rules! tst { }}; } - #[derive(Debug, PartialEq)] enum TstIteratorAction { - GoLeft, Visit, GoMiddle, - GoRight + GoRight, } use self::TstIteratorAction::*; - /// A [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values of the tree. See [`iter`]( struct.Tst.html#method.iter) method for a brief /// description with a short example. #[derive(Debug)] pub struct TstIterator<'a, T: 'a> { - todo_i: Vec<(&'a Node, TstIteratorAction)>, last_i: Option<&'a Node>, todo_j: Vec<(&'a Node, TstIteratorAction)>, - last_j: Option<&'a Node> + last_j: Option<&'a Node>, } - macro_rules! gen_it_path { - - ($path_of_x:ident, $todo_x:ident, $a1:expr, $a2:expr) => ( - + ($path_of_x:ident, $todo_x:ident, $a1:expr, $a2:expr) => { pub fn $path_of_x(&self) -> String { - let mut path = String::new(); for todo in self.$todo_x.iter() { - if todo.1 == $a1 || todo.1 == $a2 { - path.push(todo.0.label); } } path } - ); + }; } - impl<'a, T> TstIterator<'a, T> { - pub fn new(tst: &'a Tst) -> Self { - TstIterator::new_from_root(&tst.root) } - fn new_from_root(root: &'a Link) -> Self { - let mut it = TstIterator { - - todo_i: Vec::new(), last_i: None, - todo_j: Vec::new(), last_j: None, + todo_i: Vec::new(), + last_i: None, + todo_j: Vec::new(), + last_j: None, }; if let Some(ref node) = root { - it.todo_i.push((node, GoLeft)); it.todo_j.push((node, GoRight)); } @@ -1569,42 +1669,30 @@ impl<'a, T> TstIterator<'a, T> { it } - gen_it_path!(current_key, todo_i, GoMiddle, GoRight); gen_it_path!(current_key_back, todo_j, Visit, GoLeft); } - impl<'a, T> Iterator for TstIterator<'a, T> { - type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action)) = self.todo_i.pop() { - match action { - GoLeft => { - self.todo_i.push((node, Visit)); if let Some(ref child) = node.left { - self.todo_i.push((child, GoLeft)); } } Visit => { - if node.value.is_some() { - if let Some(node_j) = self.last_j { - if ptr::eq(node, node_j) { - self.todo_i.clear(); self.todo_j.clear(); @@ -1617,7 +1705,6 @@ impl<'a, T> Iterator for TstIterator<'a, T> { self.todo_i.push((node, GoMiddle)); if let Some(ref value) = node.value { - self.last_i = Some(node); found = Some(value); @@ -1626,19 +1713,15 @@ impl<'a, T> Iterator for TstIterator<'a, T> { } GoMiddle => { - self.todo_i.push((node, GoRight)); if let Some(ref child) = node.middle { - self.todo_i.push((child, GoLeft)); } } GoRight => { - if let Some(ref child) = node.right { - self.todo_i.push((child, GoLeft)); } } @@ -1649,47 +1732,33 @@ impl<'a, T> Iterator for TstIterator<'a, T> { } } - impl<'a, T> IntoIterator for &'a Tst { - type Item = &'a T; type IntoIter = TstIterator<'a, T>; fn into_iter(self) -> Self::IntoIter { - self.iter() } } - impl<'a, T> DoubleEndedIterator for TstIterator<'a, T> { - fn next_back(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action)) = self.todo_j.pop() { - match action { - GoRight => { - self.todo_j.push((node, GoMiddle)); if let Some(ref child) = node.right { - self.todo_j.push((child, GoRight)); } } Visit => { - if node.value.is_some() { - if let Some(node_i) = self.last_i { - if ptr::eq(node, node_i) { - self.todo_i.clear(); self.todo_j.clear(); @@ -1702,7 +1771,6 @@ impl<'a, T> DoubleEndedIterator for TstIterator<'a, T> { self.todo_j.push((node, GoLeft)); if let Some(ref value) = node.value { - self.last_j = Some(node); found = Some(value); @@ -1711,19 +1779,15 @@ impl<'a, T> DoubleEndedIterator for TstIterator<'a, T> { } GoMiddle => { - self.todo_j.push((node, Visit)); if let Some(ref child) = node.middle { - self.todo_j.push((child, GoRight)); } } GoLeft => { - if let Some(ref child) = node.left { - self.todo_j.push((child, GoRight)); } } @@ -1734,159 +1798,140 @@ impl<'a, T> DoubleEndedIterator for TstIterator<'a, T> { } } - /// A [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key begins with `prefix`. See [`iter_complete`]( /// struct.Tst.html#method.iter_complete) method for a brief description with a short example. #[derive(Debug)] pub struct TstCompleteIterator<'a, T: 'a> { - it: TstIterator<'a, T>, - prefix: String + prefix: String, } - impl<'a, T> TstCompleteIterator<'a, T> { - pub fn new(tst: &'a Tst, key_prefix: &str) -> Self { - let mut key_tail = key_prefix.chars(); TstCompleteIterator { - - it : match key_tail.next() { - + it: match key_tail.next() { None => TstIterator::::new(tst), Some(label) => { - let new_root = find_complete_root_r(&tst.root, label, key_tail); TstIterator::::new_from_root(new_root) } }, - prefix: key_prefix.to_string() + prefix: key_prefix.to_string(), } } - pub fn current_key(&self) -> String { - self.prefix.clone() + &self.it.current_key() } - pub fn current_key_back(&self) -> String { - self.prefix.clone() + &self.it.current_key_back() } } - impl<'a, T> Iterator for TstCompleteIterator<'a, T> { - type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - self.it.next() } } - impl<'a, T> DoubleEndedIterator for TstCompleteIterator<'a, T> { - fn next_back(&mut self) -> Option<&'a T> { - - self.it.next_back() + self.it.next_back() } } - /// A [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key is _close_ to `key`. See [`iter_neighbor`]( /// struct.Tst.html#method.iter_neighbor) method for a brief description with a short example. #[derive(Debug)] pub struct TstNeighborIterator<'a, 'b, T: 'a> { - - todo_i: Vec<(&'a Node, TstIteratorAction, Option, Chars<'b>, usize, usize)>, + todo_i: Vec<( + &'a Node, + TstIteratorAction, + Option, + Chars<'b>, + usize, + usize, + )>, last_i: Option<&'a Node>, - todo_j: Vec<(&'a Node, TstIteratorAction, Option, Chars<'b>, usize, usize)>, - last_j: Option<&'a Node> + todo_j: Vec<( + &'a Node, + TstIteratorAction, + Option, + Chars<'b>, + usize, + usize, + )>, + last_j: Option<&'a Node>, } - impl<'a, 'b, T> TstNeighborIterator<'a, 'b, T> { - pub fn new(tst: &'a Tst, key: &'b str, range: usize) -> Self { - let mut it = TstNeighborIterator { - - todo_i: Vec::new(), last_i: None, - todo_j: Vec::new(), last_j: None, + todo_i: Vec::new(), + last_i: None, + todo_j: Vec::new(), + last_j: None, }; if let Some(ref node) = &tst.root { - let mut key_tail = key.chars(); let key_len = key.chars().count(); let label = key_tail.next(); - let tail_len = if key_len == 0 { 0 } else {key_len-1 }; + let tail_len = if key_len == 0 { 0 } else { key_len - 1 }; - it.todo_i.push((node, GoLeft, label, key_tail.clone(), tail_len, range)); - it.todo_j.push((node, GoRight, label, key_tail, tail_len, range)); + it.todo_i + .push((node, GoLeft, label, key_tail.clone(), tail_len, range)); + it.todo_j + .push((node, GoRight, label, key_tail, tail_len, range)); } it } - gen_it_path!(current_key, todo_i, GoMiddle, GoRight); gen_it_path!(current_key_back, todo_j, Visit, GoLeft); } - impl<'a, 'b, T> Iterator for TstNeighborIterator<'a, 'b, T> { - type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action, label, mut key_tail, tail_len, range)) = self.todo_i.pop() { - match action { - GoLeft => { - - self.todo_i.push((node, Visit, label, key_tail.clone(), tail_len, range)); + self.todo_i + .push((node, Visit, label, key_tail.clone(), tail_len, range)); if let Some(label) = label { - if range == 0 && label >= node.label { - continue; } } if let Some(ref child) = node.left { - - self.todo_i.push((child, GoLeft, label, key_tail, tail_len, range)); + self.todo_i + .push((child, GoLeft, label, key_tail, tail_len, range)); } } Visit => { - if node.value.is_some() { - if let Some(node_j) = self.last_j { - if ptr::eq(node, node_j) { - self.todo_i.clear(); self.todo_j.clear(); @@ -1896,24 +1941,26 @@ impl<'a, 'b, T> Iterator for TstNeighborIterator<'a, 'b, T> { } } - self.todo_i.push((node, GoMiddle, label, key_tail, tail_len, range)); + self.todo_i + .push((node, GoMiddle, label, key_tail, tail_len, range)); if let Some(ref value) = node.value { - let delta = match label { - None => 1, - Some(label) => if label==node.label { 0 } else { 1 } - + Some(label) => { + if label == node.label { + 0 + } else { + 1 + } + } }; if range >= delta { - let new_range = range - delta; - if tail_len <= new_range { - + if tail_len <= new_range { self.last_i = Some(node); found = Some(value); @@ -1924,43 +1971,44 @@ impl<'a, 'b, T> Iterator for TstNeighborIterator<'a, 'b, T> { } GoMiddle => { - - self.todo_i.push((node, GoRight, label, key_tail.clone(), tail_len, range)); + self.todo_i + .push((node, GoRight, label, key_tail.clone(), tail_len, range)); let delta = match label { - None => 1, - Some(label) => if label==node.label { 0 } else { 1 } + Some(label) => { + if label == node.label { + 0 + } else { + 1 + } + } }; if range >= delta { - let new_range = range - delta; let new_label = key_tail.next(); - let new_len = if tail_len > 0 { tail_len-1 } else { tail_len }; + let new_len = if tail_len > 0 { tail_len - 1 } else { tail_len }; if let Some(ref child) = node.middle { - - self.todo_i.push((child, GoLeft, new_label, key_tail, new_len, new_range)); + self.todo_i + .push((child, GoLeft, new_label, key_tail, new_len, new_range)); } } } GoRight => { - if let Some(label) = label { - if range == 0 && label <= node.label { - continue; } } if let Some(ref child) = node.right { - - self.todo_i.push((child, GoLeft, label, key_tail, tail_len, range)); + self.todo_i + .push((child, GoLeft, label, key_tail, tail_len, range)); } } } @@ -1970,43 +2018,32 @@ impl<'a, 'b, T> Iterator for TstNeighborIterator<'a, 'b, T> { } } - impl<'a, 'b, T> DoubleEndedIterator for TstNeighborIterator<'a, 'b, T> { - fn next_back(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action, label, mut key_tail, tail_len, range)) = self.todo_j.pop() { - match action { - GoRight => { - - self.todo_j.push((node, GoMiddle, label, key_tail.clone(), tail_len, range)); + self.todo_j + .push((node, GoMiddle, label, key_tail.clone(), tail_len, range)); if let Some(label) = label { - if range == 0 && label <= node.label { - continue; } } if let Some(ref child) = node.right { - - self.todo_j.push((child, GoRight, label, key_tail, tail_len, range)); + self.todo_j + .push((child, GoRight, label, key_tail, tail_len, range)); } } Visit => { - if node.value.is_some() { - if let Some(node_i) = self.last_i { - if ptr::eq(node, node_i) { - self.todo_i.clear(); self.todo_j.clear(); @@ -2016,24 +2053,26 @@ impl<'a, 'b, T> DoubleEndedIterator for TstNeighborIterator<'a, 'b, T> { } } - self.todo_j.push((node, GoLeft, label, key_tail, tail_len, range)); + self.todo_j + .push((node, GoLeft, label, key_tail, tail_len, range)); if let Some(ref value) = node.value { - let delta = match label { - None => 1, - Some(label) => if label==node.label { 0 } else { 1 } - + Some(label) => { + if label == node.label { + 0 + } else { + 1 + } + } }; if range >= delta { - let new_range = range - delta; - if tail_len <= new_range { - + if tail_len <= new_range { self.last_j = Some(node); found = Some(value); @@ -2044,44 +2083,44 @@ impl<'a, 'b, T> DoubleEndedIterator for TstNeighborIterator<'a, 'b, T> { } GoMiddle => { - - self.todo_j.push((node, Visit, label, key_tail.clone(), tail_len, range)); + self.todo_j + .push((node, Visit, label, key_tail.clone(), tail_len, range)); let delta = match label { - None => 1, - Some(label) => if label==node.label { 0 } else { 1 } - + Some(label) => { + if label == node.label { + 0 + } else { + 1 + } + } }; if range >= delta { - let new_range = range - delta; let new_label = key_tail.next(); - let new_len = if tail_len > 0 { tail_len-1 } else { tail_len }; + let new_len = if tail_len > 0 { tail_len - 1 } else { tail_len }; if let Some(ref child) = node.middle { - - self.todo_j.push((child, GoRight, new_label, key_tail, new_len, new_range)); + self.todo_j + .push((child, GoRight, new_label, key_tail, new_len, new_range)); } } } GoLeft => { - if let Some(label) = label { - if range == 0 && label >= node.label { - continue; } } if let Some(ref child) = node.left { - - self.todo_j.push((child, GoRight, label, key_tail, tail_len, range)); + self.todo_j + .push((child, GoRight, label, key_tail, tail_len, range)); } } } @@ -2091,45 +2130,39 @@ impl<'a, 'b, T> DoubleEndedIterator for TstNeighborIterator<'a, 'b, T> { } } - /// A [double-ended]( http://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) iterator which /// successively returns all values whose key _matches_ `pattern`. See [`iter_crossword`]( /// struct.Tst.html#method.iter_crossword) method for a brief description with a short example. #[derive(Debug)] pub struct TstCrosswordIterator<'a, 'b, T: 'a> { - todo_i: Vec<(&'a Node, TstIteratorAction, char, Chars<'b>, usize)>, last_i: Option<&'a Node>, todo_j: Vec<(&'a Node, TstIteratorAction, char, Chars<'b>, usize)>, last_j: Option<&'a Node>, - joker: char + joker: char, } - impl<'a, 'b, T> TstCrosswordIterator<'a, 'b, T> { - pub fn new(tst: &'a Tst, key: &'b str, joker: char) -> Self { - let mut it = TstCrosswordIterator { - - todo_i: Vec::new(), last_i: None, - todo_j: Vec::new(), last_j: None, + todo_i: Vec::new(), + last_i: None, + todo_j: Vec::new(), + last_j: None, joker, - }; if let Some(ref node) = &tst.root { - let mut key_tail = key.chars(); if let Some(label) = key_tail.next() { + let tail_len = key.chars().count() - 1; - let tail_len = key.chars().count()-1; - - it.todo_i.push((node, GoLeft, label, key_tail.clone(), tail_len)); + it.todo_i + .push((node, GoLeft, label, key_tail.clone(), tail_len)); it.todo_j.push((node, GoRight, label, key_tail, tail_len)); } } @@ -2137,45 +2170,33 @@ impl<'a, 'b, T> TstCrosswordIterator<'a, 'b, T> { it } - gen_it_path!(current_key, todo_i, GoMiddle, GoRight); gen_it_path!(current_key_back, todo_j, Visit, GoLeft); } - impl<'a, 'b, T> Iterator for TstCrosswordIterator<'a, 'b, T> { - type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action, label, mut key_tail, tail_len)) = self.todo_i.pop() { - match action { - GoLeft => { - - self.todo_i.push((node, Visit, label, key_tail.clone(), tail_len)); + self.todo_i + .push((node, Visit, label, key_tail.clone(), tail_len)); if label == self.joker || label < node.label { - if let Some(ref child) = node.left { - self.todo_i.push((child, GoLeft, label, key_tail, tail_len)); } } } Visit => { - if node.value.is_some() { - if let Some(node_j) = self.last_j { - if ptr::eq(node, node_j) { - self.todo_i.clear(); self.todo_j.clear(); @@ -2185,12 +2206,11 @@ impl<'a, 'b, T> Iterator for TstCrosswordIterator<'a, 'b, T> { } } - self.todo_i.push((node, GoMiddle, label, key_tail, tail_len)); + self.todo_i + .push((node, GoMiddle, label, key_tail, tail_len)); if let Some(ref value) = node.value { - if tail_len == 0 && (label == self.joker || label == node.label) { - self.last_i = Some(node); found = Some(value); @@ -2200,27 +2220,27 @@ impl<'a, 'b, T> Iterator for TstCrosswordIterator<'a, 'b, T> { } GoMiddle => { - - self.todo_i.push((node, GoRight, label, key_tail.clone(), tail_len)); + self.todo_i + .push((node, GoRight, label, key_tail.clone(), tail_len)); if label == self.joker || label == node.label { - if let Some(ref child) = node.middle { - if let Some(new_label) = key_tail.next() { - - self.todo_i.push((child, GoLeft, new_label, key_tail, tail_len-1)); + self.todo_i.push(( + child, + GoLeft, + new_label, + key_tail, + tail_len - 1, + )); } } } } GoRight => { - if label == self.joker || label > node.label { - if let Some(ref child) = node.right { - self.todo_i.push((child, GoLeft, label, key_tail, tail_len)); } } @@ -2232,38 +2252,28 @@ impl<'a, 'b, T> Iterator for TstCrosswordIterator<'a, 'b, T> { } } - impl<'a, 'b, T> DoubleEndedIterator for TstCrosswordIterator<'a, 'b, T> { - fn next_back(&mut self) -> Option<&'a T> { - let mut found = None; while let Some((node, action, label, mut key_tail, tail_len)) = self.todo_j.pop() { - match action { - GoRight => { - - self.todo_j.push((node, GoMiddle, label, key_tail.clone(), tail_len)); + self.todo_j + .push((node, GoMiddle, label, key_tail.clone(), tail_len)); if label == self.joker || label > node.label { - if let Some(ref child) = node.right { - - self.todo_j.push((child, GoRight, label, key_tail, tail_len)); + self.todo_j + .push((child, GoRight, label, key_tail, tail_len)); } } } Visit => { - if node.value.is_some() { - if let Some(node_i) = self.last_i { - if ptr::eq(node, node_i) { - self.todo_i.clear(); self.todo_j.clear(); @@ -2276,9 +2286,7 @@ impl<'a, 'b, T> DoubleEndedIterator for TstCrosswordIterator<'a, 'b, T> { self.todo_j.push((node, GoLeft, label, key_tail, tail_len)); if let Some(ref value) = node.value { - if tail_len == 0 && (label == self.joker || label == node.label) { - self.last_j = Some(node); found = Some(value); @@ -2288,28 +2296,29 @@ impl<'a, 'b, T> DoubleEndedIterator for TstCrosswordIterator<'a, 'b, T> { } GoMiddle => { - - self.todo_j.push((node, Visit, label, key_tail.clone(), tail_len)); + self.todo_j + .push((node, Visit, label, key_tail.clone(), tail_len)); if label == self.joker || label == node.label { - if let Some(ref child) = node.middle { - if let Some(new_label) = key_tail.next() { - - self.todo_j.push((child, GoRight, new_label, key_tail, tail_len-1)); + self.todo_j.push(( + child, + GoRight, + new_label, + key_tail, + tail_len - 1, + )); } } } } GoLeft => { - if label == self.joker || label < node.label { - if let Some(ref child) = node.left { - - self.todo_j.push((child, GoRight, label, key_tail, tail_len)); + self.todo_j + .push((child, GoRight, label, key_tail, tail_len)); } } } diff --git a/tests/tests.rs b/tests/tests.rs index 24573a7..2d3ec6a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,18 +1,14 @@ extern crate ternary_tree; use ternary_tree::Tst; - #[test] fn tst_create_empty_map() { - let map: Tst = Tst::new(); assert_eq!(map.len(), 0); } - #[test] fn tst_insert_some_key_value() { - let mut map = Tst::new(); assert_eq!(map.len(), 0); @@ -21,10 +17,8 @@ fn tst_insert_some_key_value() { assert_eq!(map.len(), 1); } - #[test] fn tst_get_some_value_by_key() { - let mut map = Tst::new(); assert_eq!(map.len(), 0); @@ -41,10 +35,8 @@ fn tst_get_some_value_by_key() { assert_eq!(v2, v1); } - #[test] fn tst_replace_some_value() { - let mut map = Tst::new(); assert_eq!(map.len(), 0); @@ -65,10 +57,8 @@ fn tst_replace_some_value() { assert_eq!(v2, Some(&"v2")); } - #[test] fn tst_get_value_back_on_empty_key() { - let mut map = Tst::new(); assert_eq!(map.len(), 0); @@ -77,22 +67,50 @@ fn tst_get_value_back_on_empty_key() { assert_eq!(map.len(), 0); } +#[test] +fn tst_remove_root() { + let mut map = Tst::new(); + map.insert("b", "B"); + map.insert("a", "A"); + map.insert("eę", "EĘ"); + map.insert("c", "C"); + map.insert("cć", "CĆ"); + map.insert("f", "F"); + map.insert("d", "D"); + assert_eq!(map.len(), 7); + assert_eq!(map.remove("b"), Some("B")); + assert_eq!(map.len(), 6); + assert_eq!(map.get("a"), Some(&"A")); + assert_eq!(map.get("b"), None); + assert_eq!(map.get("c"), Some(&"C")); + assert_eq!(map.get("cć"), Some(&"CĆ")); + assert_eq!(map.get("d"), Some(&"D")); + assert_eq!(map.get("e"), None); + assert_eq!(map.get("eę"), Some(&"EĘ")); + assert_eq!(map.get("f"), Some(&"F")); +} -const RANDOM_VEC_123 : [&str; 16] = ["aba", "ab", "bc", "ac", "abc", "a", "b", "aca", "caa", "cbc", "bac", "c", "cca", "aab", "abb", "aa"]; - -const RANDOM_VEC_123_BIS : [&str; 16] = [ "cca", "aa", "bac", "aba", "b", "bc", "c", "ac", "aab", "ab", "abc", "abb", "a", "caa", "aca", "cbc" ]; +const RANDOM_VEC_123: [&str; 16] = [ + "aba", "ab", "bc", "ac", "abc", "a", "b", "aca", "caa", "cbc", "bac", "c", "cca", "aab", "abb", + "aa", +]; -const SORTED_VEC_123 : [&str; 16] = ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "b", "bac", "bc", "c", "caa", "cbc", "cca"]; +const RANDOM_VEC_123_BIS: [&str; 16] = [ + "cca", "aa", "bac", "aba", "b", "bc", "c", "ac", "aab", "ab", "abc", "abb", "a", "caa", "aca", + "cbc", +]; +const SORTED_VEC_123: [&str; 16] = [ + "a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "b", "bac", "bc", "c", "caa", "cbc", + "cca", +]; fn get_sample_map_abc_count() -> Tst { - let mut map = Tst::new(); let mut count = 0; for k in RANDOM_VEC_123.iter() { - - count+=1; + count += 1; let old_value = map.insert(k, count); assert_eq!(old_value, None); assert_eq!(map.len(), count); @@ -101,15 +119,12 @@ fn get_sample_map_abc_count() -> Tst { map } - fn get_sample_map_abc_abc() -> Tst<&'static str> { - let mut map = Tst::new(); let mut count = 0; for k in RANDOM_VEC_123.iter() { - - count+=1; + count += 1; let old_value = map.insert(k, *k); assert_eq!(old_value, None); assert_eq!(map.len(), count); @@ -118,17 +133,14 @@ fn get_sample_map_abc_abc() -> Tst<&'static str> { map } - fn get_sample_map_abc_abc_with_unicode() -> Tst { - let mut map = Tst::new(); let mut count = 0; for k in RANDOM_VEC_123.iter() { - - count+=1; - let key = "🗝".to_owned()+k; - let val = "📦".to_owned()+k; + count += 1; + let key = "🗝".to_owned() + k; + let val = "📦".to_owned() + k; let old_value = map.insert(&key, val); assert_eq!(old_value, None); assert_eq!(map.len(), count); @@ -137,23 +149,39 @@ fn get_sample_map_abc_abc_with_unicode() -> Tst { map } +#[test] +fn tst_get_nth() { + let map = get_sample_map_abc_abc(); + for (n, expected) in SORTED_VEC_123.iter().enumerate() { + let (key, value) = map.get_nth(n).unwrap(); + assert_eq!(&key, expected); + assert_eq!(value == expected, true); + } +} #[test] -fn tst_insert_and_get_more_key_value() { +fn tst_random() { + let mut map = get_sample_map_abc_count(); + for i in 0..1000 { + map.insert(RANDOM_VEC_123[i % RANDOM_VEC_123.len()], i); + map.verify(); + map.remove(RANDOM_VEC_123_BIS[(i * i) % RANDOM_VEC_123_BIS.len()]); + map.verify(); + } +} +#[test] +fn tst_insert_and_get_more_key_value() { let map = get_sample_map_abc_count(); for k in SORTED_VEC_123.iter() { - let value = map.get(k); assert_eq!(*value.unwrap() > 0, true); } } - #[test] fn tst_iterate_over_empty_tree() { - let empty_map: Tst = Tst::new(); assert_eq!(empty_map.len(), 0); @@ -166,10 +194,8 @@ fn tst_iterate_over_empty_tree() { assert_eq!(it.next_back(), None); } - #[test] fn tst_iterate_over_values() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -185,7 +211,6 @@ fn tst_iterate_over_values() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -195,27 +220,22 @@ fn tst_iterate_over_values() { assert_eq!(it.next(), None); } - #[test] fn tst_iterate_over_values_with_for_loop() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); let mut v = Vec::new(); for value in &map { - v.push(*value); } assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_iterate_over_values_with_peek_and_co() { - let map = get_sample_map_abc_count(); assert_eq!(map.len(), 16); @@ -234,13 +254,11 @@ fn tst_iterate_over_values_with_peek_and_co() { let sum = map.iter().fold(0, |acc, v| acc + *v); let n = map.len(); - assert_eq!(sum, n*(n+1)/2); + assert_eq!(sum, n * (n + 1) / 2); } - #[test] fn tst_iterate_over_values_backward() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -256,7 +274,6 @@ fn tst_iterate_over_values_backward() { let mut v = Vec::new(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -268,10 +285,8 @@ fn tst_iterate_over_values_backward() { assert_eq!(it.next_back(), None); } - #[test] fn tst_iterate_over_values_backward_with_rev() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -287,7 +302,6 @@ fn tst_iterate_over_values_backward_with_rev() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -299,10 +313,8 @@ fn tst_iterate_over_values_backward_with_rev() { assert_eq!(it.next(), None); } - #[test] fn tst_iterate_over_values_from_both_end() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -310,7 +322,6 @@ fn tst_iterate_over_values_from_both_end() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -325,7 +336,6 @@ fn tst_iterate_over_values_from_both_end() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -344,13 +354,9 @@ fn tst_iterate_over_values_from_both_end() { let mut vj = Vec::new(); for i in 0..map.len() { - - if i%2 == 0 { - + if i % 2 == 0 { vi.push(*it.next().unwrap()); - } else { - vj.push(*it.next_back().unwrap()); } } @@ -364,10 +370,8 @@ fn tst_iterate_over_values_from_both_end() { assert_eq!(vj, ["aca", "b", "bac", "bc", "c", "caa", "cbc", "cca"]); } - #[test] fn tst_visit_values() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -378,10 +382,8 @@ fn tst_visit_values() { assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_visit_complete_values() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -391,18 +393,16 @@ fn tst_visit_complete_values() { map.visit_complete_values("bc", |s| assert_eq!(s, &"woups")); let mut v = Vec::new(); - map.visit_complete_values("ab", |s| {v.push(s.clone())}); + map.visit_complete_values("ab", |s| v.push(s.clone())); assert_eq!(v, ["aba", "abb", "abc"]); v.clear(); - map.visit_complete_values("", |s| {v.push(s.clone())}); + map.visit_complete_values("", |s| v.push(s.clone())); assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_visit_neighbor_values() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -412,46 +412,47 @@ fn tst_visit_neighbor_values() { map.visit_neighbor_values("abc", 0, |s| assert_eq!(s, &"abc")); let mut v = Vec::new(); - map.visit_neighbor_values("abc", 1, |s| {v.push(s.clone())}); + map.visit_neighbor_values("abc", 1, |s| v.push(s.clone())); assert_eq!(v, ["ab", "aba", "abb", "abc", "cbc"]); v.clear(); - map.visit_neighbor_values("abc", 2, |s| {v.push(s.clone())}); - assert_eq!(v, ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"]); + map.visit_neighbor_values("abc", 2, |s| v.push(s.clone())); + assert_eq!( + v, + ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"] + ); v.clear(); - map.visit_neighbor_values("abc", 3, |s| {v.push(s.clone())}); + map.visit_neighbor_values("abc", 3, |s| v.push(s.clone())); assert_eq!(v, SORTED_VEC_123); v.clear(); - map.visit_neighbor_values("xxxx", 4, |s| {v.push(s.clone())}); + map.visit_neighbor_values("xxxx", 4, |s| v.push(s.clone())); assert_eq!(v, SORTED_VEC_123); v.clear(); - map.visit_neighbor_values("", 0, |s| {v.push(s.clone())}); + map.visit_neighbor_values("", 0, |s| v.push(s.clone())); assert_eq!(v.is_empty(), true); v.clear(); - map.visit_neighbor_values("", 1, |s| {v.push(s.clone())}); + map.visit_neighbor_values("", 1, |s| v.push(s.clone())); assert_eq!(v, ["a", "b", "c"]); v.clear(); - map.visit_neighbor_values("", 2, |s| {v.push(s.clone())}); + map.visit_neighbor_values("", 2, |s| v.push(s.clone())); assert_eq!(v, ["a", "aa", "ab", "ac", "b", "bc", "c"]); v.clear(); - map.visit_neighbor_values("", 3, |s| {v.push(s.clone())}); + map.visit_neighbor_values("", 3, |s| v.push(s.clone())); assert_eq!(v, SORTED_VEC_123); v.clear(); - map.visit_neighbor_values("", 4, |s| {v.push(s.clone())}); + map.visit_neighbor_values("", 4, |s| v.push(s.clone())); assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_visit_crossword_values() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -478,7 +479,10 @@ fn tst_visit_crossword_values() { v.clear(); map.visit_crossword_values("???", '?', |s| v.push(s.clone())); - assert_eq!(v, ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"]); + assert_eq!( + v, + ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"] + ); v.clear(); map.visit_crossword_values("????", '?', |s| v.push(s.clone())); @@ -489,10 +493,8 @@ fn tst_visit_crossword_values() { assert_eq!(v, ["aba", "aca"]); } - #[test] fn tst_iterate_with_complete() { - let empty_map: Tst = Tst::new(); assert_eq!(empty_map.len(), 0); @@ -523,7 +525,6 @@ fn tst_iterate_with_complete() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -535,7 +536,6 @@ fn tst_iterate_with_complete() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -555,10 +555,8 @@ fn tst_iterate_with_complete() { assert_eq!(it.next(), None); } - #[test] fn tst_iterate_with_neighbor() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -566,7 +564,6 @@ fn tst_iterate_with_neighbor() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -578,7 +575,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -590,7 +586,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -602,7 +597,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -614,11 +608,13 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } - assert_eq!(v, ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"]); + assert_eq!( + v, + ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"] + ); //////////////////////////////////////////////////// @@ -626,7 +622,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -638,7 +633,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -650,7 +644,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -662,7 +655,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -674,7 +666,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -686,7 +677,6 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -698,30 +688,27 @@ fn tst_iterate_with_neighbor() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_fix_unicode_chars_in_key_bug() { - let map = get_sample_map_abc_abc_with_unicode(); assert_eq!(map.len(), 16); let mut v = Vec::new(); - map.visit_neighbor_values("🗝abc", 0, |s| {v.push(s.clone())}); + map.visit_neighbor_values("🗝abc", 0, |s| v.push(s.clone())); assert_eq!(v, ["📦abc"]); v.clear(); - map.visit_neighbor_values("🗝abc", 1, |s| {v.push(s.clone())}); + map.visit_neighbor_values("🗝abc", 1, |s| v.push(s.clone())); assert_eq!(v, ["📦ab", "📦aba", "📦abb", "📦abc", "📦cbc"]); v.clear(); - map.visit_neighbor_values("xabc", 2, |s| {v.push(s.clone())}); + map.visit_neighbor_values("xabc", 2, |s| v.push(s.clone())); assert_eq!(v, ["📦ab", "📦aba", "📦abb", "📦abc", "📦cbc"]); //////////////////////////////////////////////////// @@ -730,7 +717,6 @@ fn tst_fix_unicode_chars_in_key_bug() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(value); } @@ -742,7 +728,6 @@ fn tst_fix_unicode_chars_in_key_bug() { v.clear(); while let Some(value) = it.next() { - v.push(value); } @@ -754,7 +739,6 @@ fn tst_fix_unicode_chars_in_key_bug() { v.clear(); while let Some(value) = it.next() { - v.push(value); } @@ -766,7 +750,6 @@ fn tst_fix_unicode_chars_in_key_bug() { v.clear(); while let Some(value) = it.next() { - v.push(value); } @@ -778,17 +761,14 @@ fn tst_fix_unicode_chars_in_key_bug() { v.clear(); while let Some(value) = it.next() { - v.push(value); } assert_eq!(v, ["📦aab", "📦bac", "📦caa"]); } - #[test] fn tst_iterate_with_neighbor_backward() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -796,7 +776,6 @@ fn tst_iterate_with_neighbor_backward() { let mut v = Vec::new(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -810,7 +789,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -822,7 +800,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -834,7 +811,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -846,7 +822,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -860,13 +835,15 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } v.reverse(); - assert_eq!(v, ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"]); + assert_eq!( + v, + ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"] + ); //////////////////////////////////////////////////// @@ -874,7 +851,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -888,7 +864,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -902,7 +877,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -914,7 +888,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -928,7 +901,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -942,7 +914,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -956,7 +927,6 @@ fn tst_iterate_with_neighbor_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -965,10 +935,8 @@ fn tst_iterate_with_neighbor_backward() { assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_iterate_with_neighbor_from_both_end() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -976,11 +944,13 @@ fn tst_iterate_with_neighbor_from_both_end() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } - assert_eq!(v, ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"]); + assert_eq!( + v, + ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"] + ); assert_eq!(it.next(), None); assert_eq!(it.next_back(), None); @@ -991,13 +961,15 @@ fn tst_iterate_with_neighbor_from_both_end() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } v.reverse(); - assert_eq!(v, ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"]); + assert_eq!( + v, + ["a", "aa", "aab", "ab", "aba", "abb", "abc", "ac", "aca", "bac", "cbc"] + ); assert_eq!(it.next_back(), None); assert_eq!(it.next(), None); @@ -1014,13 +986,9 @@ fn tst_iterate_with_neighbor_from_both_end() { let mut vj = Vec::new(); for i in 0..count { - - if i%2 == 0 { - + if i % 2 == 0 { vi.push(*it.next().unwrap()); - } else { - vj.push(*it.next_back().unwrap()); } } @@ -1034,10 +1002,8 @@ fn tst_iterate_with_neighbor_from_both_end() { assert_eq!(vj, ["abc", "ac", "aca", "bac", "cbc"]); } - #[test] fn tst_iterate_with_crossword() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1045,7 +1011,6 @@ fn tst_iterate_with_crossword() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -1057,7 +1022,6 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -1069,7 +1033,6 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -1081,7 +1044,6 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -1093,7 +1055,6 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } @@ -1105,11 +1066,13 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } - assert_eq!(v, ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"]); + assert_eq!( + v, + ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"] + ); //////////////////////////////////////////////////// @@ -1117,17 +1080,14 @@ fn tst_iterate_with_crossword() { v.clear(); while let Some(value) = it.next() { - v.push(*value); } assert_eq!(v.is_empty(), true); } - #[test] fn tst_iterate_with_crossword_backward() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1135,7 +1095,6 @@ fn tst_iterate_with_crossword_backward() { let mut v = Vec::new(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1149,7 +1108,6 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1163,7 +1121,6 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1177,7 +1134,6 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1191,7 +1147,6 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1205,13 +1160,15 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } v.reverse(); - assert_eq!(v, ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"]); + assert_eq!( + v, + ["aab", "aba", "abb", "abc", "aca", "bac", "caa", "cbc", "cca"] + ); //////////////////////////////////////////////////// @@ -1219,7 +1176,6 @@ fn tst_iterate_with_crossword_backward() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1228,10 +1184,8 @@ fn tst_iterate_with_crossword_backward() { assert_eq!(v.is_empty(), true); } - #[test] fn tst_iterate_with_crossword_from_both_end() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1239,7 +1193,6 @@ fn tst_iterate_with_crossword_from_both_end() { let mut v = Vec::new(); while let Some(value) = it.next() { - v.push(*value); } @@ -1254,7 +1207,6 @@ fn tst_iterate_with_crossword_from_both_end() { v.clear(); while let Some(value) = it.next_back() { - v.push(*value); } @@ -1277,13 +1229,9 @@ fn tst_iterate_with_crossword_from_both_end() { let mut vj = Vec::new(); for i in 0..count { - - if i%2 == 0 { - + if i % 2 == 0 { vi.push(*it.next().unwrap()); - } else { - vj.push(*it.next_back().unwrap()); } } @@ -1297,10 +1245,8 @@ fn tst_iterate_with_crossword_from_both_end() { assert_eq!(vj, ["caa"]); } - #[test] fn tst_insert_and_remove_some_key_value() { - let mut empty_map: Tst = Tst::new(); assert_eq!(empty_map.len(), 0); @@ -1339,14 +1285,11 @@ fn tst_insert_and_remove_some_key_value() { assert_eq!(map.len(), 0); } - #[test] fn tst_insert_and_remove_more_key_value() { - let mut map = get_sample_map_abc_abc(); for k in RANDOM_VEC_123_BIS.iter() { - let len = map.len(); { @@ -1357,17 +1300,17 @@ fn tst_insert_and_remove_more_key_value() { let value = map.remove(k); assert_eq!(value, Some(*k)); - assert_eq!(map.len(), len-1); + assert_eq!(map.len(), len - 1); { let value = map.get(k); assert_eq!(value, None); - assert_eq!(map.len(), len-1); + assert_eq!(map.len(), len - 1); } let value = map.remove(k); assert_eq!(value, None); - assert_eq!(map.len(), len-1); + assert_eq!(map.len(), len - 1); } assert_eq!(map.len(), 0); @@ -1397,10 +1340,8 @@ fn tst_insert_and_remove_more_key_value() { assert_eq!(map.len(), 0); } - #[test] fn tst_stats_on_insert_and_remove() { - let empty_map: Tst = Tst::new(); let s1 = empty_map.stat(); @@ -1412,11 +1353,11 @@ fn tst_stats_on_insert_and_remove() { assert_eq!(s1.count.values, 0); assert_eq!(s1.count.values, empty_map.len()); - //node struct size should be around 32 bytes on x64 + //node struct size should be around 40 bytes on x64 assert_eq!(s1.bytes.node >= 16, true); assert_eq!(s1.bytes.node <= 64, true); - //main tree struct size should be around 16 bytes on x64 + //main tree struct size should be around 8 bytes on x64 assert_eq!(s1.bytes.total >= 8, true); assert_eq!(s1.bytes.total <= 32, true); @@ -1431,27 +1372,83 @@ fn tst_stats_on_insert_and_remove() { assert_eq!(s2.count.values, 16); assert_eq!(s2.count.values, map.len()); - //node struct size should be around 48 bytes on x64 + //node struct size should be around 56 bytes on x64 assert_eq!(s2.bytes.node >= 24, true); assert_eq!(s2.bytes.node <= 96, true); - //total size should be around 976 bytes on x64 + //total size should be around 1128 bytes on x64 assert_eq!(s2.bytes.total >= 488, true); - assert_eq!(s2.bytes.total <= 16+20*48, true); + assert_eq!(s2.bytes.total <= 16 + 20 * 56, true); assert_eq!(s1.bytes.node < s2.bytes.node, true); assert_eq!(s1.bytes.total < s2.bytes.total, true); use ternary_tree::DistStat; - assert_eq!(s2.dist[0], DistStat { matches: 0, sides: 3, depth: 0 }); - assert_eq!(s2.dist[1], DistStat { matches: 3, sides: 7, depth: 1 }); - assert_eq!(s2.dist[2], DistStat { matches: 4, sides: 4, depth: 2 }); - assert_eq!(s2.dist[3], DistStat { matches: 9, sides: 1, depth: 5 }); - assert_eq!(s2.dist[4], DistStat { matches: 0, sides: 1, depth: 3 }); - assert_eq!(s2.dist[5], DistStat { matches: 0, sides: 0, depth: 3 }); - assert_eq!(s2.dist[6], DistStat { matches: 0, sides: 0, depth: 1 }); - assert_eq!(s2.dist[7], DistStat { matches: 0, sides: 0, depth: 1 }); + assert_eq!( + s2.dist[0], + DistStat { + matches: 0, + sides: 3, + depth: 0 + } + ); + assert_eq!( + s2.dist[1], + DistStat { + matches: 3, + sides: 7, + depth: 1 + } + ); + assert_eq!( + s2.dist[2], + DistStat { + matches: 4, + sides: 4, + depth: 2 + } + ); + assert_eq!( + s2.dist[3], + DistStat { + matches: 9, + sides: 1, + depth: 5 + } + ); + assert_eq!( + s2.dist[4], + DistStat { + matches: 0, + sides: 1, + depth: 3 + } + ); + assert_eq!( + s2.dist[5], + DistStat { + matches: 0, + sides: 0, + depth: 3 + } + ); + assert_eq!( + s2.dist[6], + DistStat { + matches: 0, + sides: 0, + depth: 1 + } + ); + assert_eq!( + s2.dist[7], + DistStat { + matches: 0, + sides: 0, + depth: 1 + } + ); assert_eq!(s2.dist.len(), 8); //////////////////////////////////////////////////// @@ -1463,7 +1460,6 @@ fn tst_stats_on_insert_and_remove() { assert_eq!(s.count.values, 0); for k in RANDOM_VEC_123.iter() { - let s1 = map.stat(); map.insert(k, *k); let s2 = map.stat(); @@ -1474,7 +1470,6 @@ fn tst_stats_on_insert_and_remove() { } for k in RANDOM_VEC_123_BIS.iter() { - let s1 = map.stat(); map.remove(k); let s2 = map.stat(); @@ -1489,10 +1484,8 @@ fn tst_stats_on_insert_and_remove() { assert_eq!(s.count.values, 0); } - #[test] fn tst_clear_some_map() { - let mut empty_map: Tst = Tst::new(); empty_map.clear(); @@ -1522,10 +1515,8 @@ fn tst_clear_some_map() { assert_eq!(s.count.values, map.len()); } - #[test] fn tst_iterate_and_read_current_key() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1534,7 +1525,6 @@ fn tst_iterate_and_read_current_key() { let mut w = Vec::new(); while let Some(value) = it.next() { - v.push(*value); w.push(it.current_key()); } @@ -1543,10 +1533,8 @@ fn tst_iterate_and_read_current_key() { assert_eq!(w, SORTED_VEC_123); } - #[test] fn tst_iterate_and_read_current_key_back() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1555,7 +1543,6 @@ fn tst_iterate_and_read_current_key_back() { let mut w = Vec::new(); while let Some(value) = it.next_back() { - v.push(*value); w.push(it.current_key_back()); } @@ -1567,10 +1554,8 @@ fn tst_iterate_and_read_current_key_back() { assert_eq!(w, SORTED_VEC_123); } - #[test] fn tst_current_key_iterators() { - let map = get_sample_map_abc_abc(); assert_eq!(map.len(), 16); @@ -1579,7 +1564,6 @@ fn tst_current_key_iterators() { let mut w = Vec::new(); while let Some(value) = it.next() { - v.push(*value); w.push(it.current_key()); } @@ -1593,7 +1577,6 @@ fn tst_current_key_iterators() { w.clear(); while let Some(value) = it.next_back() { - v.push(*value); w.push(it.current_key_back()); } @@ -1607,7 +1590,6 @@ fn tst_current_key_iterators() { w.clear(); while let Some(value) = it.next() { - v.push(*value); w.push(it.current_key()); } @@ -1621,7 +1603,6 @@ fn tst_current_key_iterators() { w.clear(); while let Some(value) = it.next_back() { - v.push(*value); w.push(it.current_key_back()); } @@ -1635,7 +1616,6 @@ fn tst_current_key_iterators() { w.clear(); while let Some(value) = it.next() { - v.push(*value); w.push(it.current_key()); } @@ -1649,7 +1629,6 @@ fn tst_current_key_iterators() { w.clear(); while let Some(value) = it.next_back() { - v.push(*value); w.push(it.current_key_back()); } @@ -1657,19 +1636,15 @@ fn tst_current_key_iterators() { assert_eq!(v, w); } - #[test] fn tst_update_some_values() { - let mut map = get_sample_map_abc_count(); assert_eq!(map.len(), 16); for k in SORTED_VEC_123.iter() { - - let value = map.get_mut(k); + let value = map.get_mut(k); if let Some(c) = value { - assert_eq!(*c > 0, true); *c = 0; } @@ -1678,7 +1653,7 @@ fn tst_update_some_values() { let mut v = Vec::new(); map.visit_values(|c| v.push(c.clone())); - assert_eq!(v, [0 ; 16]); + assert_eq!(v, [0; 16]); //////////////////////////////////////////////////// @@ -1687,7 +1662,7 @@ fn tst_update_some_values() { v.clear(); map.visit_values(|c| v.push(c.clone())); - assert_eq!(v, [1 ; 16]); + assert_eq!(v, [1; 16]); //////////////////////////////////////////////////// @@ -1717,10 +1692,8 @@ fn tst_update_some_values() { assert_eq!(v, [1, 2, 2, 3, 4, 3, 3, 2, 4, 1, 1, 1, 1, 1, 3, 1]); } - #[test] fn tst_create_with_macro() { - use ternary_tree::tst; let map = tst!["aba" => "aba", "ab" => "ab", "bc" => "bc", "ac" => "ac", @@ -1737,24 +1710,78 @@ fn tst_create_with_macro() { assert_eq!(stat.count.values, 16); assert_eq!(stat.count.values, map.len()); - //node struct size should be around 48 bytes on x64 - assert_eq!(stat.bytes.node >= 24, true); - assert_eq!(stat.bytes.node <= 96, true); + //node struct size should be around 56 bytes on x64 + assert_eq!(stat.bytes.node, 56); - //total size should be around 976 bytes on x64 - assert_eq!(stat.bytes.total >= 488, true); - assert_eq!(stat.bytes.total <= 16+20*48, true); + //total size should be around 1128 bytes on x64 + assert_eq!(stat.bytes.total, 8 + 20 * 56); use ternary_tree::DistStat; - assert_eq!(stat.dist[0], DistStat { matches: 0, sides: 3, depth: 0 }); - assert_eq!(stat.dist[1], DistStat { matches: 3, sides: 7, depth: 1 }); - assert_eq!(stat.dist[2], DistStat { matches: 4, sides: 4, depth: 2 }); - assert_eq!(stat.dist[3], DistStat { matches: 9, sides: 1, depth: 5 }); - assert_eq!(stat.dist[4], DistStat { matches: 0, sides: 1, depth: 3 }); - assert_eq!(stat.dist[5], DistStat { matches: 0, sides: 0, depth: 3 }); - assert_eq!(stat.dist[6], DistStat { matches: 0, sides: 0, depth: 1 }); - assert_eq!(stat.dist[7], DistStat { matches: 0, sides: 0, depth: 1 }); + assert_eq!( + stat.dist[0], + DistStat { + matches: 0, + sides: 3, + depth: 0 + } + ); + assert_eq!( + stat.dist[1], + DistStat { + matches: 3, + sides: 7, + depth: 1 + } + ); + assert_eq!( + stat.dist[2], + DistStat { + matches: 4, + sides: 4, + depth: 2 + } + ); + assert_eq!( + stat.dist[3], + DistStat { + matches: 9, + sides: 1, + depth: 5 + } + ); + assert_eq!( + stat.dist[4], + DistStat { + matches: 0, + sides: 1, + depth: 3 + } + ); + assert_eq!( + stat.dist[5], + DistStat { + matches: 0, + sides: 0, + depth: 3 + } + ); + assert_eq!( + stat.dist[6], + DistStat { + matches: 0, + sides: 0, + depth: 1 + } + ); + assert_eq!( + stat.dist[7], + DistStat { + matches: 0, + sides: 0, + depth: 1 + } + ); assert_eq!(stat.dist.len(), 8); let mut v = Vec::new(); @@ -1764,10 +1791,8 @@ fn tst_create_with_macro() { assert_eq!(v, SORTED_VEC_123); } - #[test] fn tst_pretty_print() { - use ternary_tree::tst; let map = tst!["ab" => "ab", "aa" => "aa", "ac" => "ac"];