-
-
Save akolybelnikov/92632a935db63c69f5aef9ded0a861fe to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains hidden or 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