|
| 1 | +use super::item::Item; |
| 2 | +use super::node::Node; |
| 3 | +use super::prefix::common_prefix; |
| 4 | +use super::regex::LazyRegex; |
| 5 | +use std::collections::HashMap; |
| 6 | + |
| 7 | +#[derive(Debug)] |
| 8 | +pub struct Leaf<V> { |
| 9 | + pub(crate) values: HashMap<String, V>, |
| 10 | + pub(crate) regex: LazyRegex, |
| 11 | +} |
| 12 | + |
| 13 | +impl<V> Leaf<V> { |
| 14 | + pub fn new(regex: &str, id: String, item: V, ignore_case: bool) -> Self { |
| 15 | + let mut values = HashMap::new(); |
| 16 | + values.insert(id, item); |
| 17 | + |
| 18 | + Leaf { |
| 19 | + values, |
| 20 | + regex: LazyRegex::new_leaf(regex, ignore_case), |
| 21 | + } |
| 22 | + } |
| 23 | + |
| 24 | + /// Insert a new item into this node |
| 25 | + pub fn insert(mut self, regex: &str, id: String, item: V) -> Item<V> { |
| 26 | + if regex == self.regex.original.as_str() { |
| 27 | + self.values.insert(id, item); |
| 28 | + |
| 29 | + return Item::Leaf(self); |
| 30 | + } |
| 31 | + |
| 32 | + let prefix = common_prefix(self.regex.original.as_str(), regex); |
| 33 | + let mut leaf_values = HashMap::new(); |
| 34 | + leaf_values.insert(id, item); |
| 35 | + |
| 36 | + let leaf = Item::Leaf(Leaf { |
| 37 | + values: leaf_values, |
| 38 | + regex: LazyRegex::new_leaf(regex, self.regex.ignore_case), |
| 39 | + }); |
| 40 | + |
| 41 | + Item::Node(Node { |
| 42 | + regex: LazyRegex::new_node(prefix, self.regex.ignore_case), |
| 43 | + children: vec![Item::Leaf(self), leaf], |
| 44 | + }) |
| 45 | + } |
| 46 | + |
| 47 | + /// Find values associated to this haystack |
| 48 | + pub fn find(&self, haystack: &str) -> Vec<&V> { |
| 49 | + if self.regex.is_match(haystack) { |
| 50 | + return self.values.values().collect(); |
| 51 | + } |
| 52 | + |
| 53 | + Vec::new() |
| 54 | + } |
| 55 | + |
| 56 | + pub fn get(&self, regex: &str) -> Vec<&V> { |
| 57 | + if self.regex.original.as_str() == regex { |
| 58 | + return self.values.values().collect(); |
| 59 | + } |
| 60 | + |
| 61 | + Vec::new() |
| 62 | + } |
| 63 | + |
| 64 | + pub fn get_mut(&mut self, regex: &str) -> Vec<&mut V> { |
| 65 | + if self.regex.original.as_str() == regex { |
| 66 | + return self.values.values_mut().collect(); |
| 67 | + } |
| 68 | + |
| 69 | + Vec::new() |
| 70 | + } |
| 71 | + |
| 72 | + /// Remove an item on this tree |
| 73 | + /// |
| 74 | + /// This method returns true if there is no more data so it can be cleaned up |
| 75 | + pub fn remove(mut self, id: &str) -> (Item<V>, Option<V>) { |
| 76 | + let removed = self.values.remove(id); |
| 77 | + |
| 78 | + match removed { |
| 79 | + None => (Item::Leaf(self), None), |
| 80 | + Some(value) => { |
| 81 | + if self.values.is_empty() { |
| 82 | + (Item::Empty(self.regex.ignore_case), Some(value)) |
| 83 | + } else { |
| 84 | + (Item::Leaf(self), Some(value)) |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + /// Length of node |
| 91 | + pub fn len(&self) -> usize { |
| 92 | + self.values.len() |
| 93 | + } |
| 94 | + |
| 95 | + pub fn regex(&self) -> &str { |
| 96 | + self.regex.original.as_str() |
| 97 | + } |
| 98 | + |
| 99 | + /// Cache current regex according to a limit and a level |
| 100 | + /// |
| 101 | + /// This method must return new limit of element cached (passed limit minus number of element cached) |
| 102 | + /// which allow other node to avoid caching extra node |
| 103 | + /// |
| 104 | + /// Implementation must not cache item if limit is equal to 0 |
| 105 | + /// Implementation must not cache item if not caching on the current node level |
| 106 | + /// |
| 107 | + /// Level argument allow to build cache on first level of the tree by priority |
| 108 | + /// Implementation must retain at which level this node is build and not do any caching |
| 109 | + /// if we are not on the current level |
| 110 | + pub fn cache(&mut self, left: u64) -> u64 { |
| 111 | + // Already cached |
| 112 | + if self.regex.compiled.is_some() { |
| 113 | + return left; |
| 114 | + } |
| 115 | + |
| 116 | + self.regex.compile(); |
| 117 | + |
| 118 | + if self.regex.compiled.is_some() { |
| 119 | + return left - 1; |
| 120 | + } |
| 121 | + |
| 122 | + left |
| 123 | + } |
| 124 | +} |
0 commit comments