Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created October 6, 2019 19:16
Show Gist options
  • Save rust-play/be066aca1540aab0fa333e7563b75e03 to your computer and use it in GitHub Desktop.
Save rust-play/be066aca1540aab0fa333e7563b75e03 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
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