use std::collections::HashMap;
use std::ptr;
use std::mem;
use control::variable_header::TopicName;
use topic_filter::TopicFilter;
struct Node<V> {
next: HashMap<String, Box<Node<V>>>,
value: Option<V>,
}
pub struct TopicMap<V> {
head: Box<Node<V>>,
size: usize,
}
impl<V> TopicMap<V> {
pub fn new() -> TopicMap<V> {
TopicMap {
head: Box::new(Node {
next: HashMap::new(),
value: None,
}),
size: 0,
}
}
pub fn len(&self) -> usize {
self.size
}
pub fn insert(&mut self, topic_name: &TopicName, value: V) -> Option<V> {
let mut cur: *mut Node<V> = &mut *self.head;
for part in topic_name.split('/') {
let next = unsafe {
(&mut *cur).next
.entry(part.to_owned())
.or_insert_with(|| Box::new(Node {
next: HashMap::new(),
value: None,
}))
};
cur = &mut **next;
}
let mut opt_val = Some(value);
unsafe {
mem::swap(&mut opt_val, &mut (&mut *cur).value);
}
if opt_val.is_none() {
self.size += 1;
}
opt_val
}
}
#[cfg(test)]
mod test {
use super::*;
use control::variable_header::TopicName;
#[test]
fn test_topic_map_insert() {
let mut map = TopicMap::new();
let name = TopicName::new("abc/def/ghi".to_owned()).unwrap();
map.insert(&name, 123);
assert_eq!(map.len(), 1);
}
}