radix_trie-0.1.5/.gitignore010064400007650000024000000000571340164150700140610ustar0000000000000000target Cargo.lock *.swp *.swo .DS_Store .cargo radix_trie-0.1.5/.travis.yml010064400007650000024000000003171353736077400142170ustar0000000000000000language: rust os: - linux before_script: - rustup component add rustfmt-preview script: - cargo test --verbose --features serde - cargo doc --no-deps --features serde - cargo fmt --all -- --check radix_trie-0.1.5/Cargo.toml.orig010064400007650000024000000012321353740027600147620ustar0000000000000000[package] name = "radix_trie" version = "0.1.5" description = "Generic radix trie data-structure." license = "MIT" authors = ["Michael Sproul "] repository = "https://github.com/michaelsproul/rust_radix_trie" documentation = "https://docs.rs/radix_trie/" readme = "README.md" keywords = ["trie", "patricia", "collection", "generic", "prefix"] categories = ["data-structures", "text-processing"] [dependencies] nibble_vec = "~0.0.3" endian-type = "0.1.2" serde = { version = "1.0", optional = true } [dev-dependencies] quickcheck = "0.4" rand = "0.3" serde_test = "1.0" [badges] travis-ci = { repository = "michaelsproul/rust_radix_trie" } radix_trie-0.1.5/Cargo.toml0000644000000024040000000000000112260ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "radix_trie" version = "0.1.5" authors = ["Michael Sproul "] description = "Generic radix trie data-structure." documentation = "https://docs.rs/radix_trie/" readme = "README.md" keywords = ["trie", "patricia", "collection", "generic", "prefix"] categories = ["data-structures", "text-processing"] license = "MIT" repository = "https://github.com/michaelsproul/rust_radix_trie" [dependencies.endian-type] version = "0.1.2" [dependencies.nibble_vec] version = "~0.0.3" [dependencies.serde] version = "1.0" optional = true [dev-dependencies.quickcheck] version = "0.4" [dev-dependencies.rand] version = "0.3" [dev-dependencies.serde_test] version = "1.0" [badges.travis-ci] repository = "michaelsproul/rust_radix_trie" radix_trie-0.1.5/CHANGELOG.md010064400007650000024000000007771353740026300137150ustar0000000000000000Changelog ==== 0.1.5: * Fix another bug related to the removal of non-existent keys (#50) * Implement `Clone` for `Trie` 0.1.4: * Fix a panic that occurred when removing non-existent keys (#40) * Reformat the code using the latest `rustfmt` 0.1.3: * Add `prefix()` method for fetching the `NibbleVec` of a trie or subtrie * Update `nibble_vec` to v0.0.4 * Make better use of lifetime elision (type signatures will look different, but are the same) 0.1.2: * Display README on crates.io (no code changes) radix_trie-0.1.5/examples/child_iter.rs010064400007650000024000000011201340164150700163530ustar0000000000000000extern crate radix_trie; use radix_trie::{Trie, TrieCommon}; fn main() { let mut t = Trie::new(); t.insert("z", 2); t.insert("aba", 5); t.insert("abb", 6); t.insert("abc", 50); // This is a bit of a hack that relies on knowing the binary representation of // strings... "abd" works, but "abz" doesn't... let ab_sum = t.get_raw_ancestor(&"abd").children().fold(0, |acc, c| { println!("Iterating over child with value: {:?}", c.value()); acc + *c.value().unwrap_or(&0) }); println!("{}", ab_sum); assert_eq!(ab_sum, 5 + 6 + 50); } radix_trie-0.1.5/examples/debug.rs010064400007650000024000000004161340164150700153420ustar0000000000000000extern crate radix_trie; use radix_trie::Trie; fn main() { let mut trie = Trie::new(); trie.insert("hello", 19u32); trie.insert("hellcat", 35u32); trie.insert("not related", 1u32); trie.insert("handle nested", 5u32); println!("{:?}", trie); } radix_trie-0.1.5/examples/opt.rs010064400007650000024000000005521340164150700150570ustar0000000000000000extern crate radix_trie; use radix_trie::*; fn main() { let mut trie = Trie::new(); let mut key = vec![]; for i in 0..10_000 { key.push(0); trie.insert(key.clone(), i); key.pop(); key.push(1); trie.insert(key.clone(), i); } //let res = trie.remove(&blow_stack); //println!("{}", res.unwrap()); } radix_trie-0.1.5/examples/string_frequency.rs010064400007650000024000000022721340164150700176450ustar0000000000000000extern crate radix_trie; use radix_trie::{Trie, TrieCommon}; fn main() { let example = "bananaphone".to_string(); // Our frequency trie will store various strings with the frequency that they are used let mut trie: Trie = Trie::new(); let v: Vec = example.chars().collect(); // We want the frequencies of all strings from 1 to 3 characters long for window_length in 1..4 { for a in v.windows(window_length) { // Create a new String to hold our key let mut s = String::new(); // Append all chars in a to the String s.extend(a); // If the value at s exists, add 1. Otherwise, assign 1 as the key's value. trie.map_with_default(s, |v| *v += 1, 1); } } // Iterate through all the values in the trie and print them with their frequencies. // Iterates and prints in lexicographic order. println!("All trie nodes"); for (k, v) in trie.iter() { println!("{}: {}", k, v); } println!("All children of 'a'"); for n in trie.subtrie(&"a".to_string()).unwrap().children() { println!("{}: {}", n.key().unwrap(), n.value().unwrap()); } } radix_trie-0.1.5/LICENSE010064400007650000024000000020711353737771000131100ustar0000000000000000The MIT License (MIT) Copyright (c) 2015 Michael Sproul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. radix_trie-0.1.5/README.md010064400007650000024000000037731353737761100133740ustar0000000000000000Rust Radix Trie ==== [![Build Status](https://travis-ci.org/michaelsproul/rust_radix_trie.svg?branch=master)](https://travis-ci.org/michaelsproul/rust_radix_trie) This is a [Radix Trie][radix-wiki] implementation in Rust, building on the lessons learnt from `TrieMap` and [Sequence Trie][seq-trie]. You can read about my experience implementing this data structure [here][radix-paper]. # Help Wanted, Enquire Within *Since writing this code I haven't used it in anger (or production) so it is no doubt in need of some maintenance, testing and optimisation love. If you would like to help out, try solving an open issue, optimise something, or just have a poke around! Thanks :)* # Features * Compressed nodes. Common key prefixes are stored only once. * Trie-specific methods to look-up closest ancestors and descendants. * Key Generic. Any type that can be serialised as a vector of bytes can be used as a key. * Safe - no unsafe code. # Documentation https://docs.rs/radix_trie/ # Usage Available on [Crates.io][] as [`radix_trie`][radix-crate]. Just add `radix_trie` to the dependencies section of your `Cargo.toml`, like so: ```toml radix_trie = "0.1" ``` # Contributors Made by: * Allan Simon ([@allan-simon](https://github.com/allan-simon)) * Andrew Smith ([@andrewcsmith](https://github.com/andrewcsmith)) * Arthur Carcano ([@NougatRillettes](https://github.com/NougatRillettes)) * Michael Sproul ([@michaelsproul](https://github.com/michaelsproul)) * Robin Lambertz ([@roblabla](https://github.com/roblabla)) * Sergey ([@Albibek](https://github.com/Albibek)) * Stuart Hinson ([@stuarth](https://github.com/stuarth)) * Vinzent Steinberg ([@vks](https://github.com/vks)) # License MIT License. Copyright © Michael Sproul and contributors 2015-present. [radix-wiki]: http://en.wikipedia.org/wiki/Radix_tree [seq-trie]: https://github.com/michaelsproul/rust_sequence_trie [radix-paper]: https://michaelsproul.github.io/rust_radix_paper/ [crates.io]: https://crates.io/ [radix-crate]: https://crates.io/crates/radix_trie radix_trie-0.1.5/src/iter.rs010064400007650000024000000112061340164150700141670ustar0000000000000000//! Iterators over key-value pairs, keys, values and child subtries. use std::iter::{FilterMap, FromIterator, Map}; use std::slice; use trie_node::TrieNode; use {NibbleVec, SubTrie, Trie, TrieKey}; // MY EYES. type Child = Box>; type RawChildIter<'a, K, V> = slice::Iter<'a, Option>>; type ChildMapFn<'a, K, V> = fn(&'a Option>) -> Option<&'a Child>; type ChildIter<'a, K, V> = FilterMap, ChildMapFn<'a, K, V>>; /// Iterator over the keys and values of a Trie. pub struct Iter<'a, K: 'a, V: 'a> { root: &'a TrieNode, root_visited: bool, stack: Vec>, } impl<'a, K, V> Iter<'a, K, V> { // TODO: make this private somehow (and same for the other iterators). pub fn new(root: &'a TrieNode) -> Iter<'a, K, V> { Iter { root: root, root_visited: false, stack: vec![], } } } /// Iterator over the keys of a Trie. pub struct Keys<'a, K: 'a, V: 'a> { inner: Map, KeyMapFn<'a, K, V>>, } type KeyMapFn<'a, K, V> = fn((&'a K, &'a V)) -> &'a K; impl<'a, K, V> Keys<'a, K, V> { pub fn new(iter: Iter<'a, K, V>) -> Keys<'a, K, V> { fn first<'b, K, V>((k, _): (&'b K, &'b V)) -> &'b K { k } Keys { inner: iter.map(first), } } } impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; fn next(&mut self) -> Option<&'a K> { self.inner.next() } } /// Iterator over the values of a Trie. pub struct Values<'a, K: 'a, V: 'a> { inner: Map, ValueMapFn<'a, K, V>>, } type ValueMapFn<'a, K, V> = fn((&'a K, &'a V)) -> &'a V; impl<'a, K, V> Values<'a, K, V> { pub fn new(iter: Iter<'a, K, V>) -> Values<'a, K, V> { fn second<'b, K, V>((_, v): (&'b K, &'b V)) -> &'b V { v } Values { inner: iter.map(second), } } } impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; fn next(&mut self) -> Option<&'a V> { self.inner.next() } } /// Iterator over the child subtries of a trie. pub struct Children<'a, K: 'a, V: 'a> { prefix: NibbleVec, inner: ChildIter<'a, K, V>, } impl<'a, K, V> Children<'a, K, V> { pub fn new(key: NibbleVec, node: &'a TrieNode) -> Self { Children { prefix: key, inner: node.child_iter(), } } } impl<'a, K, V> Iterator for Children<'a, K, V> { type Item = SubTrie<'a, K, V>; fn next(&mut self) -> Option> { self.inner.next().map(|node| SubTrie { prefix: self.prefix.clone().join(&node.key), node: node, }) } } impl TrieNode { /// Helper function to get all the non-empty children of a node. fn child_iter(&self) -> ChildIter { fn id(x: &Option>) -> Option<&Child> { x.as_ref() } self.children.iter().filter_map(id) } /// Get the key and value of a node as a pair. fn kv_as_pair(&self) -> Option<(&K, &V)> { self.key_value.as_ref().map(|kv| (&kv.key, &kv.value)) } } enum IterAction<'a, K: 'a, V: 'a> { Push(&'a TrieNode), Pop, } impl<'a, K, V> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); fn next(&mut self) -> Option { use self::IterAction::*; // Visit each node as it is reached from its parent (with special root handling). if !self.root_visited { self.root_visited = true; self.stack.push(self.root.child_iter()); if let Some(kv) = self.root.kv_as_pair() { return Some(kv); } } loop { let action = match self.stack.last_mut() { Some(stack_top) => match stack_top.next() { Some(child) => Push(child), None => Pop, }, None => return None, }; match action { Push(trie) => { self.stack.push(trie.child_iter()); if let Some(kv) = trie.kv_as_pair() { return Some(kv); } } Pop => { self.stack.pop(); } } } } } impl FromIterator<(K, V)> for Trie where K: TrieKey, { fn from_iter(iter: T) -> Trie where T: IntoIterator, { let mut trie = Trie::new(); for (k, v) in iter { trie.insert(k, v); } trie } } radix_trie-0.1.5/src/keys.rs010064400007650000024000000114771353736077400142270ustar0000000000000000use endian_type::{BigEndian, LittleEndian}; use std::ffi::OsString; use std::path::{Path, PathBuf}; use NibbleVec; /// Trait for types which can be used to key a Radix Trie. /// /// Types that implement this trait should be convertible to a vector of half-bytes (nibbles) /// such that no two instances of the type convert to the same vector. /// To protect against faulty behaviour, the trie will **panic** if it finds two distinct keys /// of type `K` which encode to the same `NibbleVec`, so be careful! /// /// If you would like to implement this trait for your own type, you need to implement /// *either* `encode_bytes` or `encode`. You only need to implement one of the two. /// If you don't implement one, your code will **panic** as soon you use the trie. /// There is no performance penalty for implementing `encode_bytes` instead of `encode`, /// so it is preferred except in the case where you require half-byte precision. /// /// Many standard types implement this trait already. Integer types are encoded *big-endian* /// by default but can be encoded little-endian using the `LittleEndian` wrapper type. pub trait TrieKey: PartialEq + Eq { /// Encode a value as a vector of bytes. fn encode_bytes(&self) -> Vec { panic!("implement this method or TrieKey::encode"); } /// Encode a value as a NibbleVec. fn encode(&self) -> NibbleVec { NibbleVec::from_byte_vec(self.encode_bytes()) } } /// Key comparison result. #[derive(Debug)] pub enum KeyMatch { /// The keys match up to the given index. Partial(usize), /// The first key is a prefix of the second. FirstPrefix, /// The second key is a prefix of the first. SecondPrefix, /// The keys match exactly. Full, } /// Compare two Trie keys. /// /// Compares `first[start_idx .. ]` to `second`, i.e. only looks at a slice of the first key. pub fn match_keys(start_idx: usize, first: &NibbleVec, second: &NibbleVec) -> KeyMatch { let first_len = first.len() - start_idx; let min_length = ::std::cmp::min(first_len, second.len()); for i in 0..min_length { if first.get(start_idx + i) != second.get(i) { return KeyMatch::Partial(i); } } match (first_len, second.len()) { (x, y) if x < y => KeyMatch::FirstPrefix, (x, y) if x == y => KeyMatch::Full, _ => KeyMatch::SecondPrefix, } } /// Check two keys for equality and panic if they differ. pub fn check_keys(key1: &K, key2: &K) where K: TrieKey, { if *key1 != *key2 { panic!("multiple-keys with the same bit representation."); } } // --- TrieKey Implementations for standard types --- /// // This blanket implementation goes into play when specialization is stabilized // impl TrieKey for T where T: Into> + Clone + Eq + PartialEq { // fn encode_bytes(&self) -> Vec { // self.clone().into() // } // } impl TrieKey for Vec { fn encode_bytes(&self) -> Vec { self.clone() } } impl TrieKey for [u8] { fn encode_bytes(&self) -> Vec { self.to_vec() } } impl TrieKey for String { fn encode_bytes(&self) -> Vec { self.as_bytes().encode_bytes() } } impl TrieKey for str { fn encode_bytes(&self) -> Vec { self.as_bytes().encode_bytes() } } impl<'a, T: ?Sized + TrieKey> TrieKey for &'a T { fn encode_bytes(&self) -> Vec { (**self).encode_bytes() } } impl<'a, T: ?Sized + TrieKey> TrieKey for &'a mut T { fn encode_bytes(&self) -> Vec { (**self).encode_bytes() } } impl TrieKey for i8 { fn encode_bytes(&self) -> Vec { let mut v: Vec = Vec::with_capacity(1); v.push(*self as u8); v } } impl TrieKey for u8 { fn encode_bytes(&self) -> Vec { let mut v: Vec = Vec::with_capacity(1); v.push(*self); v } } #[cfg(unix)] impl TrieKey for PathBuf { fn encode_bytes(&self) -> Vec { use std::os::unix::ffi::OsStringExt; let str: OsString = self.clone().into(); str.into_vec() } } #[cfg(unix)] impl TrieKey for Path { fn encode_bytes(&self) -> Vec { use std::os::unix::ffi::OsStrExt; self.as_os_str().as_bytes().encode_bytes() } } impl TrieKey for LittleEndian where T: Eq + Copy, { fn encode_bytes(&self) -> Vec { self.as_bytes().encode_bytes() } } impl TrieKey for BigEndian where T: Eq + Copy, { fn encode_bytes(&self) -> Vec { self.as_bytes().to_vec() } } macro_rules! int_keys { ( $( $t:ty ),* ) => { $( impl TrieKey for $t { fn encode_bytes(&self) -> Vec { let be: BigEndian<$t> = From::from(*self); be.encode_bytes() } } )* }; } int_keys!(u16, u32, u64, i16, i32, i64, usize, isize); radix_trie-0.1.5/src/lib.rs010064400007650000024000000037571353736742600140250ustar0000000000000000//! A wonderful, fast, safe, generic radix trie implementation. //! //! To get started, see the docs for `Trie` below. // #![warn(missing_docs)] extern crate endian_type; extern crate nibble_vec; #[cfg(test)] extern crate quickcheck; #[cfg(test)] extern crate rand; pub use keys::TrieKey; pub use nibble_vec::NibbleVec; pub use trie_common::TrieCommon; use trie_node::TrieNode; #[macro_use] mod macros; pub mod iter; mod keys; #[cfg(feature = "serde")] mod serde; mod subtrie; mod traversal; mod trie; mod trie_common; mod trie_node; #[cfg(test)] mod qc_test; #[cfg(test)] mod test; const BRANCH_FACTOR: usize = 16; /// Data-structure for storing and querying string-like keys and associated values. /// /// Any keys which share a common *prefix* are stored below a single copy of that prefix. /// This saves space, and also allows the longest prefix of any given key to be found. /// /// You can read more about Radix Tries on [Wikipedia][radix-wiki]. /// /// Lots of the methods on `Trie` return optional values - they can be composed /// nicely using `Option::and_then`. /// /// [radix-wiki]: http://en.wikipedia.org/wiki/Radix_tree #[derive(Debug, Clone)] pub struct Trie { /// The number of values stored in this sub-trie (this node and all descendants). length: usize, /// The main content of this trie. node: TrieNode, } /// Immutable view of a sub-tree a larger trie. #[derive(Debug)] pub struct SubTrie<'a, K: 'a, V: 'a> { prefix: NibbleVec, node: &'a TrieNode, } /// Mutable view of a sub-tree of a larger trie. #[derive(Debug)] pub struct SubTrieMut<'a, K: 'a, V: 'a> { prefix: NibbleVec, length: &'a mut usize, node: &'a mut TrieNode, } /// Wrapper for subtrie lookup results. /// /// When fetching from a subtrie, if the prefix is wrong you'll get an `Err(())`. /// Otherwise you'll get an `Ok(_)`, where the contained option value is what would ordinarily /// be returned by get/insert/whatever. pub type SubTrieResult = Result, ()>; radix_trie-0.1.5/src/macros.rs010064400007650000024000000001761353736077400145320ustar0000000000000000// Identity macro to allow expansion of the "mutability" token tree. macro_rules! id { ($e:item) => { $e }; } radix_trie-0.1.5/src/qc_test.rs010064400007650000024000000162221353736540200147000ustar0000000000000000//! Proper testing, with QuickCheck. use quickcheck::{quickcheck, Arbitrary, Gen}; use std::collections::{HashMap, HashSet}; use std::iter::FromIterator; use {Trie, TrieCommon, TrieKey}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] struct Key(Vec); #[derive(Clone, Debug)] struct RandomKeys(HashSet); const MAX_KEYS: usize = 512; const KEY_RUN_LEN: usize = 8; const KEY_MAX_VAL: u8 = 4; impl Arbitrary for Key { fn arbitrary(g: &mut G) -> Key { let len = g.gen::() % KEY_RUN_LEN; let mut key = Vec::with_capacity(len); for _ in 0..len { key.push(g.gen::() % KEY_MAX_VAL); } Key(key) } } impl Key { fn extend_random(&self, g: &mut G) -> Key { self.extend(Key::arbitrary(g)) } fn extend(&self, other: Key) -> Key { let mut key = self.clone(); key.0.extend(other.0); key } fn len(&self) -> usize { self.0.len() } } impl TrieKey for Key { fn encode_bytes(&self) -> Vec { self.0.clone() } } impl Arbitrary for RandomKeys { fn arbitrary(g: &mut G) -> RandomKeys { let num_keys = g.gen::() % MAX_KEYS; let mut keys = Vec::with_capacity(num_keys); keys.push(Key::arbitrary(g)); for _ in 0..num_keys { match g.gen::() % 10 { // Generate a new random key. 1 => keys.push(Key::arbitrary(g)), // Extend an existing key. _ => { let i = g.gen::() % keys.len(); let key = keys[i].extend_random(g); keys.push(key); } } } RandomKeys(HashSet::from_iter(keys)) } } #[test] fn insert_all_remove_all() { fn prop(RandomKeys(keys): RandomKeys) -> bool { let mut trie = Trie::new(); let mut length = 0; for k in &keys { if trie.insert(k.clone(), k.len()).is_some() { return false; } length += 1; if trie.len() != length { return false; } } if !trie.check_integrity() { return false; } for k in &keys { if trie.get(&k) != Some(&k.len()) { return false; } if trie.remove(&k) != Some(k.len()) { return false; } length -= 1; if trie.len() != length { return false; } if trie.get(&k).is_some() { return false; } } trie.check_integrity() } quickcheck(prop as fn(RandomKeys) -> bool); } #[test] fn subtrie() { fn prop(RandomKeys(keys): RandomKeys) -> bool { let half = keys.len() / 2; let first_half = keys.iter().take(half).map(|k| (k.clone(), k.len())); let trie = Trie::from_iter(first_half); // Check node existence for inserted keys. for k in keys.iter().take(half) { match trie.subtrie(&k) { Some(node) => { if node.value() != Some(&k.len()) { return false; } } None => return false, } } // Check that nodes for non-inserted keys don't have values. for k in keys.iter().skip(half) { if let Some(node) = trie.subtrie(&k) { if node.value().is_some() { return false; } } } trie.check_integrity() } quickcheck(prop as fn(RandomKeys) -> bool); } // trie.subtrie(k1).get(k2) should be the same as trie.get(k2) if k1 is a prefix of k2. #[test] fn subtrie_get() { fn prop(trie_keys: RandomKeys, k1: Key, k2: Key) -> bool { let mut trie = length_trie(trie_keys.0); trie.insert(k1.clone(), k1.len()); let subtrie = trie.subtrie(&k1).unwrap(); if k2.0.starts_with(&k1.0) { subtrie.get(&k2).unwrap() == trie.get(&k2) } else { subtrie.get(&k2).is_err() } } quickcheck(prop as fn(RandomKeys, Key, Key) -> bool); } #[test] fn subtrie_mut_get() { fn prop(trie_keys: RandomKeys, k1: Key, k2: Key) -> bool { let mut trie = length_trie(trie_keys.0); trie.insert(k1.clone(), k1.len()); let subtrie = trie.subtrie_mut(&k1).unwrap(); let ok = if k2.0.starts_with(&k1.0) { subtrie.get(&k2).is_ok() } else { subtrie.get(&k2).is_err() }; ok && trie.check_integrity() } quickcheck(prop as fn(RandomKeys, Key, Key) -> bool); } #[test] fn subtrie_insert() { fn prop(trie_keys: RandomKeys, key_suffixes: RandomKeys, k1: Key) -> bool { let mut trie = length_trie(trie_keys.0); trie.insert(k1.clone(), k1.len()); { let mut subtrie = trie.subtrie_mut(&k1).unwrap(); let insert_keys = key_suffixes .0 .into_iter() .map(|x| k1.extend(x)) .collect::>(); for k in insert_keys.iter() { assert!(subtrie.insert(k.clone(), k.len()).is_ok()); } for k in insert_keys.iter() { match subtrie.get(k) { Ok(Some(_)) => (), _ => return false, } } } trie.check_integrity() } quickcheck(prop as fn(RandomKeys, RandomKeys, Key) -> bool); } // Construct a trie from a set of keys, with each key mapped to its length. fn length_trie(keys: HashSet) -> Trie { let mut t = Trie::new(); for k in keys { let len = k.len(); t.insert(k, len); } t } #[test] fn remove_non_existent() { fn prop(RandomKeys(insert_keys): RandomKeys, RandomKeys(remove_keys): RandomKeys) -> bool { let mut trie = length_trie(insert_keys.clone()); for k in remove_keys { if !insert_keys.contains(&k) && trie.remove(&k).is_some() { return false; } } trie.check_integrity() } quickcheck(prop as fn(RandomKeys, RandomKeys) -> bool); } #[test] fn keys_iter() { fn prop(RandomKeys(keys): RandomKeys) -> bool { let trie = length_trie(keys.clone()); let trie_keys: HashSet = trie.keys().cloned().collect(); trie_keys == keys } quickcheck(prop as fn(RandomKeys) -> bool); } #[test] fn values_iter() { // Create a map of values to frequencies. fn frequency_map>(values: I) -> HashMap { let mut map = HashMap::new(); for v in values { let current_val = map.entry(v).or_insert(0); *current_val += 1; } map } fn prop(RandomKeys(keys): RandomKeys) -> bool { let trie = length_trie(keys.clone()); let trie_values: HashMap = frequency_map(trie.values().cloned()); let key_values = frequency_map(keys.into_iter().map(|k| k.len())); trie_values == key_values } quickcheck(prop as fn(RandomKeys) -> bool); } radix_trie-0.1.5/src/serde.rs010064400007650000024000000131171340164150700143310ustar0000000000000000extern crate serde; use self::serde::ser::SerializeMap; use self::serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use super::{Trie, TrieCommon, TrieKey}; use std::fmt::{self, Formatter}; use std::marker::PhantomData; impl Serialize for Trie where K: Serialize + TrieKey, V: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut map = serializer.serialize_map(Some(self.len()))?; for (k, v) in self.iter() { map.serialize_entry(k, v)?; } map.end() } } struct TrieVisitor { marker: PhantomData>, } impl TrieVisitor { fn new() -> Self { TrieVisitor { marker: PhantomData, } } } impl<'a, K, V> de::Visitor<'a> for TrieVisitor where K: Deserialize<'a> + Clone + Eq + PartialEq + TrieKey, V: Deserialize<'a>, { type Value = Trie; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { write!(formatter, "a serialized trie") } fn visit_map(self, mut visitor: M) -> Result where M: de::MapAccess<'a>, { let mut values = Trie::new(); while let Some((key, value)) = visitor.next_entry()? { values.insert(key, value); } Ok(values) } fn visit_unit(self) -> Result where E: de::Error, { Ok(Trie::new()) } } impl<'a, K, V> Deserialize<'a> for Trie where K: Deserialize<'a> + Clone + Eq + PartialEq + TrieKey, V: Deserialize<'a>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { // Instantiate our Visitor and ask the Deserializer to drive // it over the input data, resulting in an instance of MyMap. deserializer.deserialize_map(TrieVisitor::new()) } } #[cfg(test)] mod test { extern crate serde_test; use self::serde_test::Token; use super::super::Trie; macro_rules! tests_de { ($($name:ident => $value:expr => $tokens:expr,)+) => { $(#[test] fn $name() { // Test ser/de roundtripping serde_test::assert_de_tokens(&$value, $tokens); })+ } } macro_rules! tests_ser { ($($name:ident => $value:expr => $tokens:expr,)+) => { $(#[test] fn $name() { serde_test::assert_ser_tokens(&$value, $tokens); })+ } } macro_rules! trie { () => { Trie::new() }; ($($key:expr => $value:expr),+) => { { let mut map = Trie::new(); $(map.insert($key, $value);)+ map } } } tests_ser! { test_ser_empty_trie => Trie::<&str, isize>::new() => &[ Token::Map { len: Some(0) }, Token::MapEnd, ], test_ser_single_element_trie => trie!["1" => 2] => &[ Token::Map { len: Some(1) }, Token::Str("1"), Token::I32(2), Token::MapEnd, ], test_ser_multiple_element_trie => trie!["1" => 2, "3" => 4] => &[ Token::Map { len: Some(2) }, Token::Str("1"), Token::I32(2), Token::Str("3"), Token::I32(4), Token::MapEnd, ], test_ser_deep_trie => trie!["1" => trie![], "2" => trie!["3" => 4, "5" => 6]] => &[ Token::Map { len: Some(2) }, Token::Str("1"), Token::Map { len: Some(0) }, Token::MapEnd, Token::Str("2"), Token::Map { len: Some(2) }, Token::Str("3"), Token::I32(4), Token::Str("5"), Token::I32(6), Token::MapEnd, Token::MapEnd, ], } tests_de! { test_de_empty_trie1 => Trie::::new() => &[ Token::Unit, ], test_de_empty_trie2 => Trie::::new() => &[ Token::Map { len: Some(0) }, Token::MapEnd, ], test_de_single_element_trie => trie!["1".to_string() => 2] => &[ Token::Map { len: Some(1) }, Token::Str("1"), Token::I32(2), Token::MapEnd, ], test_de_multiple_element_trie => trie!["1".to_string() => 2, "3".to_string() => 4] => &[ Token::Map { len: Some(2) }, Token::Str("1"), Token::I32(2), Token::Str("3"), Token::I32(4), Token::MapEnd, ], test_de_deep_trie => trie!["1".to_string() => trie![], "2".to_string() => trie!["3".to_string() => 4, "5".to_string() => 6]] => &[ Token::Map { len: Some(2) }, Token::Str("1"), Token::Map { len: Some(0) }, Token::MapEnd, Token::Str("2"), Token::Map { len: Some(2) }, Token::Str("3"), Token::I32(4), Token::Str("5"), Token::I32(6), Token::MapEnd, Token::MapEnd, ], test_de_empty_trie3 => Trie::::new() => &[ Token::UnitStruct { name: "Anything" }, ], test_de_empty_trie4 => Trie::::new() => &[ Token::Struct { name: "Anything", len: 0, }, Token::StructEnd, ], } } radix_trie-0.1.5/src/subtrie.rs010064400007650000024000000062101340164150700147000ustar0000000000000000use keys::*; use std::borrow::Borrow; use trie_node::TrieNode; use {NibbleVec, SubTrie, SubTrieMut, SubTrieResult}; impl<'a, K, V> SubTrie<'a, K, V> where K: TrieKey, { /// Look up the value for the given key, which should be an extension of this subtrie's key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get(&self, key: &Q) -> SubTrieResult<&V> where K: Borrow, Q: TrieKey, { subtrie_get(&self.prefix, self.node, key) } } fn subtrie_get<'a, K, Q: ?Sized, V>( prefix: &NibbleVec, node: &'a TrieNode, key: &Q, ) -> SubTrieResult<&'a V> where K: TrieKey, K: Borrow, Q: TrieKey, { let key_enc = key.encode(); match match_keys(0, prefix, &key_enc) { KeyMatch::Full => Ok(node.value()), KeyMatch::FirstPrefix => Ok(node .get(&stripped(key_enc, prefix)) .and_then(TrieNode::value)), _ => Err(()), } } impl<'a, K, V> SubTrieMut<'a, K, V> where K: TrieKey, { /// Mutable reference to the node's value. pub fn value_mut(&mut self) -> Option<&mut V> { self.node.value_mut() } /// Look up the value for the given key, which should be an extension of this subtrie's key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get(&self, key: &Q) -> SubTrieResult<&V> where K: Borrow, Q: TrieKey, { subtrie_get(&self.prefix, &*self.node, key) } /// Insert a value in this subtrie. The key should be an extension of this subtrie's key. pub fn insert(&mut self, key: K, value: V) -> SubTrieResult { let key_enc = key.encode(); let previous = match match_keys(0, &self.prefix, &key_enc) { KeyMatch::Full => self.node.replace_value(key, value), KeyMatch::FirstPrefix => self .node .insert(key, value, stripped(key_enc, &self.prefix)), _ => { return Err(()); } }; if previous.is_none() { *self.length += 1; } Ok(previous) } /// Remove a value from this subtrie. The key should be an extension of this subtrie's key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn remove(&mut self, key: &Q) -> SubTrieResult where K: Borrow, Q: TrieKey, { let key_enc = key.encode(); let removed = match match_keys(0, &self.prefix, &key_enc) { KeyMatch::Full => self.node.take_value(key), KeyMatch::FirstPrefix => self.node.remove(key), _ => { return Err(()); } }; if removed.is_some() { *self.length -= 1; } Ok(removed) } } fn stripped(mut key: NibbleVec, prefix: &NibbleVec) -> NibbleVec { key.split(prefix.len()) } radix_trie-0.1.5/src/test.rs010064400007650000024000000300441353736751400142210ustar0000000000000000use keys::TrieKey; use std::collections::HashSet; use std::iter::FromIterator; use {Trie, TrieCommon}; const TEST_DATA: [(&'static str, u32); 7] = [ ("abcdefgh", 19), ("abcdef", 18), ("abcd", 17), ("ab", 16), ("a", 15), ("acbdef", 30), ("bcdefgh", 29), ]; fn test_trie() -> Trie<&'static str, u32> { let mut trie = Trie::new(); for &(key, val) in &TEST_DATA { trie.insert(key, val); assert!(trie.check_integrity()); } trie } #[test] fn get_nonexistant() { let trie = test_trie(); assert!(trie.get(&"nonexistant").is_none()); assert!(trie.get(&"").is_none()); } #[test] fn subtrie_nonexistant() { let trie = test_trie(); assert!(trie.subtrie(&"nonexistant").is_none()); assert!(trie.subtrie(&"").is_some()); } #[test] fn unicode() { let mut trie = Trie::new(); trie.insert("bär", 1); trie.insert("bären", 2); assert_eq!(*trie.get("bär").unwrap(), 1); let values = trie .get_raw_descendant("bä") .unwrap() .values() .collect::>(); assert_eq!([1, 2].iter().collect::>(), values); } #[test] fn subtrie() { let mut trie = Trie::new(); trie.insert("hello", 55); assert!(trie.subtrie(&"h").is_none()); assert!(trie.subtrie(&"hello").is_some()); } #[test] fn subtrie_string() { let mut trie = Trie::new(); trie.insert("hello".to_string(), 55); let h = "h".to_string(); let hello = "hello".to_string(); assert!(trie.subtrie(&h).is_none()); assert!(trie.subtrie(&hello).is_some()); } #[test] fn empty_key() { let mut trie = test_trie(); trie.insert(&"", 99); assert_eq!(*trie.get(&"").unwrap(), 99); assert_eq!(trie.remove(&""), Some(99)); } #[test] fn insert() { let trie = test_trie(); for &(key, val) in &TEST_DATA { assert_eq!(*trie.get(&key).unwrap(), val); } assert!(trie.check_integrity()); assert_eq!(trie.len(), TEST_DATA.len()); } #[test] fn insert_replace() { let mut trie = Trie::new(); assert_eq!(trie.insert("haskell", 18), None); let length = trie.len(); assert_eq!(trie.insert("haskell", 36), Some(18)); assert_eq!(trie.len(), length); } #[test] fn map_with_default() { let mut trie = test_trie(); trie.map_with_default(&"abcd", |x| *x = *x + 1, 42); assert_eq!(*trie.get(&"abcd").unwrap(), 17 + 1); trie.map_with_default(&"zzz", |x| *x = *x + 1, 42); assert_eq!(*trie.get(&"zzz").unwrap(), 42); } #[test] fn remove() { let mut trie = test_trie(); // Remove. for &(key, val) in &TEST_DATA { let res = trie.remove(&key); assert_eq!(res, Some(val)); assert!(trie.check_integrity()); } // Check non-existance. for &(key, _) in &TEST_DATA { assert!(trie.get(&key).is_none()); } } #[test] fn remove_simple() { let mut trie = Trie::new(); trie.insert("HELL", 66); trie.insert("HELLO", 77); let val = trie.remove(&"HELLO"); assert_eq!(val, Some(77)); } #[test] fn remove_non_existent() { let mut trie = Trie::new(); trie.insert("acab", true); assert_eq!(trie.remove(&"abc"), None); assert_eq!(trie.remove(&"acaba"), None); assert_eq!(trie.remove(&"a"), None); assert_eq!(trie.remove(&""), None); assert_eq!(trie.len(), 1); trie.insert("acaz", true); assert_eq!(trie.remove(&"acb"), None); assert_eq!(trie.remove(&"acaca"), None); assert_eq!(trie.remove(&"aca"), None); assert_eq!(trie.len(), 2); } #[test] fn nearest_ancestor_root() { let mut trie = Trie::new(); trie.insert("", 55); assert_eq!(trie.get_ancestor_value(&""), Some(&55)); } #[test] fn nearest_ancestor() { let trie = test_trie(); assert_eq!(trie.get_ancestor_value(&""), None); // Test identity prefixes. for &(key, val) in &TEST_DATA { assert_eq!(trie.get_ancestor_value(&key), Some(&val)); } assert_eq!(trie.get_ancestor_value(&"abcdefg"), trie.get(&"abcdef")); assert_eq!(trie.get_ancestor_value(&"abcde"), trie.get(&"abcd")); assert_eq!(trie.get_ancestor_value(&"aauksdjk"), trie.get(&"a")); } #[test] fn nearest_ancestor_no_child_fn() { let mut t = Trie::new(); t.insert("ab", 5); let anc = t.get_ancestor(&"abc").unwrap(); assert_eq!(*anc.value().unwrap(), 5); } #[test] fn raw_ancestor() { let mut t = Trie::new(); for &(key, _) in &TEST_DATA { assert_eq!(t.get_raw_ancestor(&key).key(), t.key()); } t.insert("wow", 0); t.insert("hella", 1); t.insert("hellb", 2); // Ancestor should be "hell" node. let anc = t.get_raw_ancestor(&"hello"); assert_eq!(anc.len(), 2); } // Check that the subtrie prefix is correct for raw_ancestor. #[test] fn raw_ancestor_prefix() { let mut t = Trie::new(); t.insert("abac", ()); t.insert("abaz", ()); let anc = t.get_raw_ancestor(&"aba"); assert_eq!(anc.prefix, "aba".encode()); } #[test] fn iter() { type Set = HashSet<(&'static str, u32)>; let trie = test_trie(); let expected = TEST_DATA.iter().map(|&x| x).collect::(); let observed = trie.iter().map(|(&k, &v)| (k, v)).collect::(); assert_eq!(expected, observed); } #[test] fn get_raw_descendant() { let trie = test_trie(); assert_eq!( trie.get_raw_descendant(&"abcdefgh").and_then(|t| t.value()), Some(&19) ); assert_eq!( trie.get_raw_descendant(&"abcdefg").and_then(|t| t.value()), Some(&19) ); assert!(trie.get_raw_descendant(&"acbg").is_none()); } #[test] fn raw_descendant_prefix() { let mut t = Trie::new(); t.insert("abczzzz", ()); t.insert("abcaaaa", ()); assert_eq!(t.get_raw_descendant(&"a").unwrap().prefix, "abc".encode()); assert_eq!(t.get_raw_descendant(&"abc").unwrap().prefix, "abc".encode()); assert_eq!( t.get_raw_descendant(&"abca").unwrap().prefix, "abcaaaa".encode() ); } #[test] fn get_prefix_bug() { let mut trie = Trie::new(); trie.insert("abdc", 5); trie.insert("abde", 6); assert!(trie.get(&"abc").is_none()); } #[test] fn get_ancestor_bug() { let mut trie = Trie::new(); trie.insert("abc", 1); trie.insert("abcde", 2); assert_eq!(trie.get_ancestor_value(&"abcdz"), Some(&1)); } #[test] fn root_replace_bug() { let mut trie = Trie::new(); trie.insert("a", ()); trie.insert("p", ()); trie.remove(&"a"); assert_eq!(trie.len(), 1); trie.remove(&"p"); assert_eq!(trie.len(), 0); } #[test] fn subtrie_insert() { let mut trie = Trie::new(); trie.insert("abc", 3); { let mut subtrie = trie.subtrie_mut(&"abc").unwrap(); assert_eq!(subtrie.insert("somerandomshit", 666), Err(())); assert_eq!(subtrie.insert("abcdef", 6), Ok(None)); assert_eq!(subtrie.insert("abc", 9), Ok(Some(3))); } assert_eq!(trie.get(&"abc"), Some(&9)); assert_eq!(trie.get(&"abcdef"), Some(&6)); assert_eq!(trie.len(), 2); } #[test] fn subtrie_len() { let trie = test_trie(); assert_eq!(trie.subtrie(&"ab").unwrap().len(), 4); assert_eq!(trie.subtrie(&"a").unwrap().len(), 6); assert_eq!(trie.subtrie(&"").unwrap().len(), trie.len()); assert_eq!(trie.subtrie(&"bcdefgh").unwrap().len(), 1); } // Subtrie functions that return references should return references valid for // the lifetime of the *original trie* from which they were borrowed, NOT // just the lifetime of the subtrie (which may be shorter). #[test] fn subtrie_lifetime() { let trie = test_trie(); let subtrie_value = { let subtrie = trie.subtrie(&"ab").unwrap(); subtrie.value() }; assert_eq!(*subtrie_value.unwrap(), 16); } #[test] fn subtrie_mut_lifetime() { let mut trie = test_trie(); let subtrie_value = { let mut subtrie = trie.subtrie_mut(&"ab").unwrap(); *subtrie.value_mut().unwrap() = 999; subtrie.value() }; assert_eq!(*subtrie_value.unwrap(), 999); } #[test] fn ancestor_key() { let trie = test_trie(); let subtrie = trie.get_ancestor(&"abcde").unwrap(); assert_eq!(*subtrie.key().unwrap(), "abcd"); assert_eq!(subtrie.prefix, "abcd".encode()); assert_eq!(*subtrie.get(&"abcdef").unwrap().unwrap(), 18); assert_eq!(*subtrie.get(&"abcdefgh").unwrap().unwrap(), 19); } #[test] fn child_subtrie_keys() { let trie = test_trie(); let subtrie = trie.subtrie(&"abcd").unwrap(); for subsubtrie in subtrie.children() { // This subtrie should be for "abcde". assert_eq!(*subsubtrie.get(&"abcdef").unwrap().unwrap(), 18); assert_eq!(*subsubtrie.get(&"abcdefgh").unwrap().unwrap(), 19); } } #[test] fn int_keys() { let mut trie = Trie::new(); trie.insert(0x00ffu64, "asdf"); trie.insert(0xdeadbeefu64, "asdf"); assert!(trie.check_integrity()); } #[test] fn from_iter() { let trie: Trie<&str, u32> = Trie::from_iter(vec![("test", 10), ("hello", 12)]); assert_eq!(*trie.get(&"test").unwrap(), 10); assert_eq!(*trie.get(&"hello").unwrap(), 12); assert_eq!(trie.len(), 2); } #[test] fn test_get_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); assert_eq!(*trie.get("/boot").unwrap(), "dir"); } #[test] fn test_get_mut_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); assert_eq!(*trie.get_mut("/boot").unwrap(), "dir"); } #[test] fn test_remove_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); assert_eq!(trie.remove("/boot").unwrap(), "dir"); } #[test] fn test_subtrie_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); trie.insert("/boot/lol".to_string(), "dir"); trie.insert("/bleh".to_string(), "ohi"); let subtrie = trie.subtrie("/boot").unwrap(); assert_eq!(*subtrie.value().unwrap(), "dir"); } #[test] fn test_subtrie_mut_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); trie.insert("/boot/lol".to_string(), "dir"); trie.insert("/bleh".to_string(), "ohi"); let subtrie = trie.subtrie_mut("/boot").unwrap(); assert_eq!(*subtrie.value().unwrap(), "dir"); } #[test] fn test_get_ancestor_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "ancestor"); trie.insert("/boot/lol".to_string(), "dir"); trie.insert("/bleh".to_string(), "ohi"); let subtrie = trie.get_ancestor("/boot/lo").unwrap(); assert_eq!(*subtrie.value().unwrap(), "ancestor"); } #[test] fn test_get_ancestor_value_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "ancestor"); trie.insert("/boot/lol".to_string(), "dir"); trie.insert("/bleh".to_string(), "ohi"); let ancestor_val = trie.get_ancestor_value("/boot/lo").unwrap(); assert_eq!(*ancestor_val, "ancestor"); } #[test] fn test_get_raw_ancestor_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "boot"); trie.insert("/boot/lol".to_string(), "dir"); trie.insert("/bleh".to_string(), "ohi"); let subtrie = trie.get_raw_ancestor("/boot/lo"); assert_eq!(*subtrie.value().unwrap(), "boot"); } #[test] fn test_get_raw_descendant_borrow() { let mut trie = Trie::new(); trie.insert("/boot".to_string(), "dir"); trie.insert("/boot/lol".to_string(), "lol"); trie.insert("/bleh".to_string(), "ohi"); let subtrie = trie.get_raw_descendant("/boot/lo").unwrap(); assert_eq!(*subtrie.value().unwrap(), "lol"); } #[test] fn test_prefix() { let mut t = Trie::::new(); t.insert(0xf1, ()); t.remove(&0xf2); t.insert(0xf2, ()); println!("{:#?}", t); assert_eq!(t.prefix(), [].as_ref()); let first = t.children().next().unwrap(); assert_eq!(first.prefix(), [0xf].as_ref()); let mut c = first.children(); let second = c.next().unwrap(); let third = c.next().unwrap(); assert!(c.next().is_none()); assert_eq!(second.prefix(), [0x1].as_ref()); assert_eq!(third.prefix(), [0x2].as_ref()); } #[test] fn clone() { let mut t1 = test_trie(); let mut t2 = t1.clone(); assert_eq!(t1, t2); t1.insert("abc", 22); assert_ne!(t1, t2); t2.insert("abc", 22); assert_eq!(t1, t2); } radix_trie-0.1.5/src/traversal.rs010064400007650000024000000266021353736466600152570ustar0000000000000000//! This module contains the core algorithms. use keys::{match_keys, KeyMatch}; use std::borrow::Borrow; use trie_node::TrieNode; use {NibbleVec, TrieKey}; use self::DescendantResult::*; impl TrieNode where K: TrieKey, { pub fn get(&self, nv: &NibbleVec) -> Option<&TrieNode> { iterative_get(self, nv) } pub fn get_mut(&mut self, nv: &NibbleVec) -> Option<&mut TrieNode> { iterative_get_mut(self, nv) } pub fn insert(&mut self, key: K, value: V, nv: NibbleVec) -> Option { iterative_insert(self, key, value, nv) } pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: TrieKey, { recursive_remove(self, key) } pub fn get_ancestor(&self, nv: &NibbleVec) -> Option<(&TrieNode, usize)> { get_ancestor(self, nv) } pub fn get_raw_ancestor(&self, nv: &NibbleVec) -> (&TrieNode, usize) { get_raw_ancestor(self, nv) } pub fn get_raw_descendant<'a>(&'a self, nv: &NibbleVec) -> Option> { get_raw_descendant(self, nv) } } macro_rules! get_func { ( name: $name:ident, trie_type: $trie_type:ty, mutability: $($mut_:tt)* ) => {id!{ fn $name<'a, K, V>(trie: $trie_type, nv: &NibbleVec) -> Option<$trie_type> { if nv.len() == 0 { return Some(trie); } let mut prev = trie; let mut depth = 0; loop { let bucket = nv.get(depth) as usize; let current = prev; if let Some(ref $($mut_)* child) = current.children[bucket] { match match_keys(depth, nv, &child.key) { KeyMatch::Full => { return Some(child); } KeyMatch::SecondPrefix => { depth += child.key.len(); prev = child; } _ => { return None; } } } else { return None; } } } }} } get_func!(name: iterative_get, trie_type: &'a TrieNode, mutability: ); get_func!(name: iterative_get_mut, trie_type: &'a mut TrieNode, mutability: mut); fn iterative_insert( trie: &mut TrieNode, key: K, value: V, mut nv: NibbleVec, ) -> Option where K: TrieKey, { if nv.len() == 0 { return trie.replace_value(key, value); } let mut prev = trie; let mut depth = 0; loop { let bucket = nv.get(depth) as usize; let current = prev; if let Some(ref mut child) = current.children[bucket] { match match_keys(depth, &nv, &child.key) { KeyMatch::Full => { return child.replace_value(key, value); } KeyMatch::Partial(idx) => { // Split the existing child. child.split(idx); // Insert the new key below the prefix node. let new_key = nv.split(depth + idx); let new_key_bucket = new_key.get(0) as usize; child.add_child( new_key_bucket, Box::new(TrieNode::with_key_value(new_key, key, value)), ); return None; } KeyMatch::FirstPrefix => { child.split(nv.len() - depth); child.add_key_value(key, value); return None; } KeyMatch::SecondPrefix => { depth += child.key.len(); prev = child; } } } else { let node_key = nv.split(depth); current.add_child( bucket, Box::new(TrieNode::with_key_value(node_key, key, value)), ); return None; } } } // TODO: clean this up and make it iterative. fn recursive_remove(trie: &mut TrieNode, key: &Q) -> Option where K: TrieKey, K: Borrow, Q: TrieKey, { let nv = key.encode(); if nv.len() == 0 { return trie.take_value(key); } let bucket = nv.get(0) as usize; let child = trie.take_child(bucket); match child { Some(mut child) => { match match_keys(0, &nv, &child.key) { KeyMatch::Full => { let result = child.take_value(key); if child.child_count != 0 { // If removing this node's value has made it a value-less node with a // single child, then merge its child. let repl = if child.child_count == 1 { get_merge_child(&mut child) } else { child }; trie.add_child(bucket, repl); } result } KeyMatch::SecondPrefix => { let depth = child.key.len(); rec_remove(trie, child, bucket, key, depth, &nv) } KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { trie.add_child(bucket, child); None } } } None => None, } } fn get_merge_child(trie: &mut TrieNode) -> Box> where K: TrieKey, { let mut child = trie.take_only_child(); // Join the child's key onto the existing one. child.key = trie.key.clone().join(&child.key); child } // Tail-recursive remove function used by `recursive_remove`. fn rec_remove( parent: &mut TrieNode, mut middle: Box>, prev_bucket: usize, key: &Q, depth: usize, nv: &NibbleVec, ) -> Option where K: TrieKey, K: Borrow, Q: TrieKey, { let bucket = nv.get(depth) as usize; let child = middle.take_child(bucket); parent.add_child(prev_bucket, middle); match child { Some(mut child) => { let middle = parent.children[prev_bucket].as_mut().unwrap(); match match_keys(depth, nv, &child.key) { KeyMatch::Full => { let result = child.take_value(key); // If this node has children, keep it. if child.child_count != 0 { // If removing this node's value has made it a value-less node with a // single child, then merge its child. let repl = if child.child_count == 1 { get_merge_child(&mut *child) } else { child }; middle.add_child(bucket, repl); } // Otherwise, if the parent node now only has a single child, merge it. else if middle.child_count == 1 && middle.key_value.is_none() { let repl = get_merge_child(middle); *middle = repl; } result } KeyMatch::SecondPrefix => { let new_depth = depth + child.key.len(); rec_remove(middle, child, bucket, key, new_depth, nv) } KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { middle.add_child(bucket, child); None } } } None => None, } } fn get_ancestor<'a, K, V>( trie: &'a TrieNode, nv: &NibbleVec, ) -> Option<(&'a TrieNode, usize)> where K: TrieKey, { if nv.len() == 0 { return trie.as_value_node().map(|node| (node, 0)); } let mut prev = trie; // The ancestor is such that all nodes upto and including `prev` have // already been considered. let mut ancestor = prev.as_value_node(); let mut depth = 0; loop { let bucket = nv.get(depth) as usize; let current = prev; if let Some(ref child) = current.children[bucket] { match match_keys(depth, nv, &child.key) { KeyMatch::Full => { return child .as_value_node() .map(|node| (node, depth + node.key.len())) .or_else(|| ancestor.map(|anc| (anc, depth))); } KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { return ancestor.map(|anc| (anc, depth)); } KeyMatch::SecondPrefix => { depth += child.key.len(); ancestor = child.as_value_node().or(ancestor); prev = child; } } } else { return ancestor.map(|anc| (anc, depth)); } } } fn get_raw_ancestor<'a, K, V>( trie: &'a TrieNode, nv: &NibbleVec, ) -> (&'a TrieNode, usize) where K: TrieKey, { if nv.len() == 0 { return (trie, 0); } let mut prev = trie; // The ancestor is such that all nodes upto and including `prev` have // already been considered. let mut ancestor = prev; let mut depth = 0; loop { let bucket = nv.get(depth) as usize; let current = prev; if let Some(ref child) = current.children[bucket] { match match_keys(depth, nv, &child.key) { KeyMatch::Full => { return (child, depth + child.key.len()); } KeyMatch::FirstPrefix | KeyMatch::Partial(_) => { return (ancestor, depth); } KeyMatch::SecondPrefix => { depth += child.key.len(); ancestor = child; prev = child; } } } else { return (ancestor, depth); } } } // Type used to propogate subtrie construction instructions to the top-level `get_raw_descendant` // method. pub enum DescendantResult<'a, K: 'a, V: 'a> { NoModification(&'a TrieNode), ExtendKey(&'a TrieNode, usize, &'a NibbleVec), } fn get_raw_descendant<'a, K, V>( trie: &'a TrieNode, nv: &NibbleVec, ) -> Option> { if nv.len() == 0 { return Some(NoModification(trie)); } let mut prev = trie; let mut depth = 0; loop { let bucket = nv.get(depth) as usize; let current = prev; if let Some(ref child) = current.children[bucket] { match match_keys(depth, nv, &child.key) { KeyMatch::Full => { return Some(NoModification(child)); } KeyMatch::FirstPrefix => { return Some(ExtendKey(child, depth, &child.key)); } KeyMatch::SecondPrefix => { depth += child.key.len(); prev = child; } _ => { return None; } } } else { return None; } } } radix_trie-0.1.5/src/trie.rs010064400007650000024000000161341353736737500142160ustar0000000000000000use std::borrow::Borrow; use traversal::DescendantResult::*; use trie_node::TrieNode; use {NibbleVec, SubTrie, SubTrieMut, Trie, TrieCommon, TrieKey}; impl Trie where K: TrieKey, { /// Create an empty Trie. pub fn new() -> Trie { Trie { length: 0, node: TrieNode::new(), } } /// Fetch a reference to the given key's corresponding value, if any. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: TrieKey, { let key_fragments = key.encode(); self.node .get(&key_fragments) .and_then(|t| t.value_checked(key)) } /// Fetch a mutable reference to the given key's corresponding value, if any. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: TrieKey, { let key_fragments = key.encode(); self.node .get_mut(&key_fragments) .and_then(|t| t.value_checked_mut(key)) } /// Insert the given key-value pair, returning any previous value associated with the key. pub fn insert(&mut self, key: K, value: V) -> Option { let key_fragments = key.encode(); let result = self.node.insert(key, value, key_fragments); if result.is_none() { self.length += 1; } result } /// Remove the value associated with the given key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: TrieKey, { let removed = self.node.remove(key); if removed.is_some() { self.length -= 1; } removed } /// Get a mutable reference to the value stored at this node, if any. pub fn value_mut(&mut self) -> Option<&mut V> { self.node.value_mut() } /// Fetch a reference to the subtrie for a given key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn subtrie<'a, Q: ?Sized>(&'a self, key: &Q) -> Option> where K: Borrow, Q: TrieKey, { let key_fragments = key.encode(); self.node .get(&key_fragments) .map(|node| node.as_subtrie(key_fragments)) } /// Fetch a mutable reference to the subtrie for a given key. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn subtrie_mut<'a, Q: ?Sized>(&'a mut self, key: &Q) -> Option> where K: Borrow, Q: TrieKey, { let key_fragments = key.encode(); let length_ref = &mut self.length; self.node .get_mut(&key_fragments) .map(move |node| node.as_subtrie_mut(key_fragments, length_ref)) } /// Fetch a reference to the closest ancestor node of the given key. /// /// If `key` is encoded as byte-vector `b`, return the node `n` in the tree /// such that `n`'s key's byte-vector is the longest possible prefix of `b`, and `n` /// has a value. /// /// Invariant: `result.is_some() => result.key_value.is_some()`. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get_ancestor<'a, Q: ?Sized>(&'a self, key: &Q) -> Option> where K: Borrow, Q: TrieKey, { let mut key_fragments = key.encode(); self.node .get_ancestor(&key_fragments) .map(|(node, node_key_len)| { key_fragments.split(node_key_len); node.as_subtrie(key_fragments) }) } /// Fetch the closest ancestor *value* for a given key. /// /// See `get_ancestor` for precise semantics, this is just a shortcut. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get_ancestor_value(&self, key: &Q) -> Option<&V> where K: Borrow, Q: TrieKey, { self.get_ancestor(key).and_then(|t| t.node.value()) } /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get_raw_ancestor<'a, Q: ?Sized>(&'a self, key: &Q) -> SubTrie<'a, K, V> where K: Borrow, Q: TrieKey, { let mut nv = key.encode(); let (ancestor_node, depth) = self.node.get_raw_ancestor(&nv); nv.split(depth); ancestor_node.as_subtrie(nv) } /// Fetch the closest descendant for a given key. /// /// If the key is in the trie, this is the same as `subtrie`. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn get_raw_descendant<'a, Q: ?Sized>(&'a self, key: &Q) -> Option> where K: Borrow, Q: TrieKey, { let mut nv = key.encode(); self.node.get_raw_descendant(&nv).map(|desc| { let (node, prefix) = match desc { NoModification(node) => (node, nv), ExtendKey(node, depth, extension) => { nv.split(depth); (node, nv.join(extension)) } }; node.as_subtrie(prefix) }) } /// Take a function `f` and apply it to the value stored at `key`. /// /// If no value is stored at `key`, store `default`. pub fn map_with_default(&mut self, key: K, f: F, default: V) where F: Fn(&mut V), { { if let Some(v) = self.get_mut(&key) { f(v); return; } } self.insert(key, default); } /// Check that the Trie invariants are satisfied - you shouldn't ever have to call this! /// Quite slow! #[doc(hidden)] pub fn check_integrity(&self) -> bool { let (ok, length) = self.node.check_integrity_recursive(&NibbleVec::new()); ok && length == self.length } } impl PartialEq for Trie where K: TrieKey, V: PartialEq, { fn eq(&self, other: &Trie) -> bool { if self.len() != other.len() { return false; } self.iter() .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) } } impl Default for Trie { fn default() -> Self { Self::new() } } radix_trie-0.1.5/src/trie_common.rs010064400007650000024000000071461340164150700155470ustar0000000000000000use iter::*; use trie_node::TrieNode; use {NibbleVec, SubTrie, SubTrieMut, Trie, TrieKey}; /// Common functionality available for tries and subtries. pub trait TrieCommon<'a, K: 'a, V: 'a>: ContainsTrieNode<'a, K, V> where K: TrieKey, Self: Sized, { /// Get the key stored at this node, if any. fn key(self) -> Option<&'a K> { self.trie_node().key() } /// Get the value stored at this node, if any. fn value(self) -> Option<&'a V> { self.trie_node().value() } /// Number of key/value pairs stored in this trie. fn len(self) -> usize; /// Determine if the Trie contains 0 key-value pairs. fn is_empty(self) -> bool { self.len() == 0 } /// Determine if the trie is a leaf node (has no children). fn is_leaf(self) -> bool { self.trie_node().child_count == 0 } /// Return an iterator over the keys and values of the Trie. fn iter(self) -> Iter<'a, K, V> { Iter::new(self.trie_node()) } /// Return an iterator over the keys of the Trie. fn keys(self) -> Keys<'a, K, V> { Keys::new(self.iter()) } /// Return an iterator over the values of the Trie. fn values(self) -> Values<'a, K, V> { Values::new(self.iter()) } /// Return an iterator over the child subtries of this node. fn children(self) -> Children<'a, K, V>; /// Get the prefix of this node. fn prefix(self) -> &'a NibbleVec { &self.trie_node().key } } /// Helper trait for Trie/SubTrie/SubTrieMut, which all contain a trie node. pub trait ContainsTrieNode<'a, K: 'a, V: 'a> where K: TrieKey, { fn trie_node(self) -> &'a TrieNode; } /// Regular trie. impl<'a, K: 'a, V: 'a> ContainsTrieNode<'a, K, V> for &'a Trie where K: TrieKey, { fn trie_node(self) -> &'a TrieNode { &self.node } } impl<'a, K: 'a, V: 'a> TrieCommon<'a, K, V> for &'a Trie where K: TrieKey, { fn len(self) -> usize { self.length } fn children(self) -> Children<'a, K, V> { Children::new(self.node.key.clone(), &self.node) } } /// Subtrie. impl<'a: 'b, 'b, K: 'a, V: 'a> ContainsTrieNode<'a, K, V> for &'b SubTrie<'a, K, V> where K: TrieKey, { fn trie_node(self) -> &'a TrieNode { self.node } } impl<'a: 'b, 'b, K: 'a, V: 'a> TrieCommon<'a, K, V> for &'b SubTrie<'a, K, V> where K: TrieKey, { fn len(self) -> usize { self.node.compute_size() } fn children(self) -> Children<'a, K, V> { Children::new(self.prefix.clone(), self.node) } } /// Mutable subtrie *by value* (consumes the subtrie). impl<'a, K: 'a, V: 'a> ContainsTrieNode<'a, K, V> for SubTrieMut<'a, K, V> where K: TrieKey, { fn trie_node(self) -> &'a TrieNode { self.node } } impl<'a, K: 'a, V: 'a> TrieCommon<'a, K, V> for SubTrieMut<'a, K, V> where K: TrieKey, { /// **Computes** from scratch. fn len(self) -> usize { self.node.compute_size() } fn children(self) -> Children<'a, K, V> { Children::new(self.prefix.clone(), self.node) } } /// Mutable subtrie *by reference* (doesn't consume the subtrie, but limited). impl<'a: 'b, 'b, K: 'a, V: 'a> ContainsTrieNode<'b, K, V> for &'b SubTrieMut<'a, K, V> where K: TrieKey, { fn trie_node(self) -> &'b TrieNode { self.node } } impl<'a: 'b, 'b, K: 'a, V: 'a> TrieCommon<'b, K, V> for &'b SubTrieMut<'a, K, V> where K: TrieKey, { fn len(self) -> usize { self.node.compute_size() } fn children(self) -> Children<'b, K, V> { Children::new(self.prefix.clone(), self.node) } } radix_trie-0.1.5/src/trie_node.rs010064400007650000024000000223061353736743700152200ustar0000000000000000use keys::*; use std::borrow::Borrow; use std::default::Default; use {NibbleVec, SubTrie, SubTrieMut, BRANCH_FACTOR}; #[derive(Debug, Clone)] pub struct TrieNode { /// Key fragments/bits associated with this node, such that joining the keys from all /// parent nodes and this node is equal to the bit-encoding of this node's key. pub key: NibbleVec, /// The key and value stored at this node. pub key_value: Option>>, /// The number of children which are Some rather than None. pub child_count: usize, /// The children of this node stored such that the first nibble of each child key /// dictates the child's bucket. pub children: [Option>>; BRANCH_FACTOR], } #[derive(Debug, Clone)] pub struct KeyValue { pub key: K, pub value: V, } macro_rules! no_children { () => { [ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ] }; } impl TrieNode where K: TrieKey, { /// Create a value-less, child-less TrieNode. pub fn new() -> TrieNode { TrieNode { key: NibbleVec::new(), key_value: None, children: no_children![], child_count: 0, } } /// Create a TrieNode with no children. pub fn with_key_value(key_fragments: NibbleVec, key: K, value: V) -> TrieNode { TrieNode { key: key_fragments, key_value: Some(Box::new(KeyValue { key: key, value: value, })), children: no_children![], child_count: 0, } } /// Get the key stored at this node, if any. pub fn key(&self) -> Option<&K> { self.key_value.as_ref().map(|kv| &kv.key) } /// Get the value stored at this node, if any. pub fn value(&self) -> Option<&V> { self.key_value.as_ref().map(|kv| &kv.value) } /// Get a mutable reference to the value stored at this node, if any. pub fn value_mut(&mut self) -> Option<&mut V> { self.key_value.as_mut().map(|kv| &mut kv.value) } /// Get the value whilst checking a key match. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn value_checked(&self, key: &Q) -> Option<&V> where K: Borrow, Q: TrieKey, { self.key_value.as_ref().map(|kv| { check_keys(kv.key.borrow(), key); &kv.value }) } /// Get a mutable value whilst checking a key match. /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn value_checked_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: TrieKey, { self.key_value.as_mut().map(|kv| { check_keys(kv.key.borrow(), key); &mut kv.value }) } /// Compute the number of keys and values in this node's subtrie. pub fn compute_size(&self) -> usize { let mut size = if self.key_value.is_some() { 1 } else { 0 }; for child in &self.children { if let Some(ref child) = *child { // TODO: could unroll this recursion size += child.compute_size(); } } size } /// Add a child at the given index, given that none exists there already. pub fn add_child(&mut self, idx: usize, node: Box>) { debug_assert!(self.children[idx].is_none()); self.child_count += 1; self.children[idx] = Some(node); } /// Remove a child at the given index, if it exists. pub fn take_child(&mut self, idx: usize) -> Option>> { self.children[idx].take().map(|node| { self.child_count -= 1; node }) } /// Helper function for removing the single child of a node. pub fn take_only_child(&mut self) -> Box> { debug_assert_eq!(self.child_count, 1); for i in 0..BRANCH_FACTOR { if let Some(child) = self.take_child(i) { return child; } } unreachable!("node with child_count 1 has no actual children"); } /// Set the key and value of a node, given that it currently lacks one. pub fn add_key_value(&mut self, key: K, value: V) { debug_assert!(self.key_value.is_none()); self.key_value = Some(Box::new(KeyValue { key: key, value: value, })); } /// Move the value out of a node, whilst checking that its key is as expected. /// Can panic (see check_keys). /// /// The key may be any borrowed form of the trie's key type, but TrieKey on the borrowed /// form *must* match those for the key type pub fn take_value(&mut self, key: &Q) -> Option where K: Borrow, Q: TrieKey, { self.key_value.take().map(|kv| { check_keys(kv.key.borrow(), key); kv.value }) } /// Replace a value, returning the previous value if there was one. pub fn replace_value(&mut self, key: K, value: V) -> Option { // TODO: optimise this? let previous = self.take_value(&key); self.add_key_value(key, value); previous } /// Get a reference to this node if it has a value. pub fn as_value_node(&self) -> Option<&TrieNode> { self.key_value.as_ref().map(|_| self) } /// Split a node at a given index in its key, transforming it into a prefix node of its /// previous self. pub fn split(&mut self, idx: usize) { // Extract all the parts of the suffix node, starting with the key. let key = self.key.split(idx); // Key-value. let key_value = self.key_value.take(); // Children. let mut children = no_children![]; for (i, child) in self.children.iter_mut().enumerate() { if child.is_some() { children[i] = child.take(); } } // Child count. let child_count = self.child_count; self.child_count = 1; // Insert the collected items below what is now an empty prefix node. let bucket = key.get(0) as usize; self.children[bucket] = Some(Box::new(TrieNode { key: key, key_value: key_value, children: children, child_count: child_count, })); } pub fn as_subtrie(&self, prefix: NibbleVec) -> SubTrie { SubTrie { prefix: prefix, node: self, } } pub fn as_subtrie_mut<'a>( &'a mut self, prefix: NibbleVec, length: &'a mut usize, ) -> SubTrieMut<'a, K, V> { SubTrieMut { prefix: prefix, length: length, node: self, } } /// Check the integrity of a trie subtree (quite costly). /// Return true and the size of the subtree if all checks are successful, /// or false and a junk value if any test fails. pub fn check_integrity_recursive(&self, prefix: &NibbleVec) -> (bool, usize) { let mut sub_tree_size = 0; let is_root = prefix.len() == 0; // Check that no value-less, non-root nodes have only 1 child. if !is_root && self.child_count == 1 && self.key_value.is_none() { println!("Value-less node with a single child."); return (false, sub_tree_size); } // Check that all non-root key vector's have length > 1. if !is_root && self.key.len() == 0 { println!("Key length is 0 at non-root node."); return (false, sub_tree_size); } // Check that the child count matches the actual number of children. let child_count = self .children .iter() .fold(0, |acc, e| acc + (e.is_some() as usize)); if child_count != self.child_count { println!( "Child count error, recorded: {}, actual: {}", self.child_count, child_count ); return (false, sub_tree_size); } // Compute the key fragments for this node, according to the trie. let trie_key = prefix.clone().join(&self.key); // Account for this node in the size check, and check its key. if let Some(ref kv) = self.key_value { sub_tree_size += 1; let actual_key = kv.key.encode(); if trie_key != actual_key { return (false, sub_tree_size); } } // Recursively check children. for i in 0..BRANCH_FACTOR { if let Some(ref child) = self.children[i] { match child.check_integrity_recursive(&trie_key) { (false, _) => return (false, sub_tree_size), (true, child_size) => sub_tree_size += child_size, } } } (true, sub_tree_size) } } impl Default for TrieNode { fn default() -> Self { Self::new() } } radix_trie-0.1.5/.cargo_vcs_info.json0000644000000001120000000000000132220ustar00{ "git": { "sha1": "5e4d720193fa21e6c874cbb6268214fbe9b9fcfb" } } radix_trie-0.1.5/Cargo.lock0000644000000247640000000000000112200ustar00# This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" version = "0.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nibble_vec" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quickcheck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "radix_trie" version = "0.1.5" dependencies = [ "endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_test 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_test" version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread-id" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "utf8-ranges" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa" "checksum quickcheck 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02c2411d418cea2364325b18a205664f9ef8252e06b2e911db97c0b0d98b1406" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" "checksum serde_test 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "55e94c89847cbce06c6919e006fc3c2da083ebefd491a233b40a6c9c42f53afe" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"