Created
October 6, 2019 19:16
-
-
Save rust-play/be066aca1540aab0fa333e7563b75e03 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
use std::collections::hash_map::Entry; | |
use std::cmp::Eq; | |
#[derive(Debug)] | |
pub struct RawKV { | |
key: String, | |
value: String | |
} | |
#[derive(Eq, PartialEq, Hash, Debug)] | |
pub enum Key { | |
Leaf(String), | |
Branch(String) | |
} | |
#[derive(Eq, PartialEq, Debug)] | |
pub enum Node { | |
Leaf { | |
key: String, | |
value: String | |
}, | |
Branch { | |
key: String, | |
children: HashMap<Key, Node> | |
} | |
} | |
impl Node { | |
fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String) { | |
match children.entry(Key::Leaf(key.clone())) { | |
Entry::Occupied(mut state) => { | |
state.insert(Node::Leaf { | |
key: key, | |
value: value | |
}); | |
}, | |
Entry::Vacant(state) => { | |
state.insert(Node::Leaf { | |
key: key, | |
value: value | |
}); | |
} | |
} | |
} | |
fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String) { | |
match children.entry(Key::Branch(key.clone())) { | |
Entry::Occupied(mut state) => { | |
// We already have a branch of that name, we just | |
// forward the call and move on | |
state.get_mut().add_value(remainder, value) | |
}, | |
Entry::Vacant(state) => { | |
// We need to create the node | |
let mut node = Node::Branch { | |
key: key, | |
children: HashMap::new() | |
}; | |
let status = node.add_value(remainder, value); | |
state.insert(node); | |
status | |
} | |
}; | |
} | |
pub fn get(&self, test: &Key) -> Option<&Node> { | |
match self { | |
Node::Branch { | |
key: _key, | |
ref children | |
} => children.get(test), | |
_ => None | |
} | |
} | |
pub fn add_value(&mut self, mut path: Vec<String>, value: String) { | |
(match self { | |
Node::Leaf { | |
key: _key, | |
value: _value | |
} => None, | |
Node::Branch { | |
key: _key, | |
ref mut children | |
} => Some(children) | |
}).map(|contents| { | |
match path.len() { | |
0 => panic!("Path cannot be empty"), | |
1 => Node::insert_key(contents, path.pop().unwrap(), value), | |
_ => Node::branch(contents, path.pop().unwrap(), path, value) | |
} | |
}); | |
} | |
} | |
pub fn into_tree(collection: Vec<RawKV>) -> Node { | |
// Create the root namespace | |
println!("Creating nodes"); | |
let mut root_node = Node::Branch { | |
key: "/".to_string(), | |
children: HashMap::new() | |
}; | |
for node in collection { | |
let mut path_elements:Vec<String> = node.key.split("/").map(|r| r.to_string()).collect(); | |
path_elements.reverse(); | |
root_node.add_value(path_elements, node.value); | |
} | |
root_node | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
fn raw(key: &str, value: &str) -> RawKV { | |
RawKV { | |
key: key.to_string(), | |
value: value.to_string() | |
} | |
} | |
fn build_key_list() -> Vec<RawKV> { | |
vec![ | |
raw("foo/bar/baz", "barry"), | |
raw("foo/bartest", "baz") | |
] | |
} | |
#[test] | |
fn builds_tree() { | |
let tree = build_key_list(); | |
let tree = into_tree(tree); | |
let foo_branch = tree.get(&Key::Branch("foo".to_string())); | |
assert!(foo_branch.is_some()); | |
let foo_branch = foo_branch.unwrap(); | |
let bartest_leaf = foo_branch.get(&Key::Leaf("bartest".to_string())); | |
assert_eq!(bartest_leaf.unwrap(), &Node::Leaf { | |
key: "bartest".to_string(), | |
value: "baz".to_string() | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment