use std::fmt;
use std::iter::FromIterator;
use std::mem::replace;
#[derive(Clone, Debug, Default)]
pub struct SequenceMap<K, V> {
sequences: Vec<(K, V)>,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FindResult<V> {
NotFound,
Incomplete,
Undecided(V),
Found(V),
}
impl<'a, V: Clone> FindResult<&'a V> {
pub fn cloned(self) -> FindResult<V> {
match self {
FindResult::NotFound => FindResult::NotFound,
FindResult::Incomplete => FindResult::Incomplete,
FindResult::Undecided(v) => FindResult::Undecided(v.clone()),
FindResult::Found(v) => FindResult::Found(v.clone()),
}
}
}
impl<K: AsRef<str>, V> SequenceMap<K, V> {
pub fn new() -> SequenceMap<K, V> {
SequenceMap::with_capacity(0)
}
pub fn with_capacity(n: usize) -> SequenceMap<K, V> {
SequenceMap{
sequences: Vec::with_capacity(n),
}
}
pub fn sequences(&self) -> &[(K, V)] {
&self.sequences
}
pub fn sequences_mut(&mut self) -> &mut [(K, V)] {
&mut self.sequences
}
pub fn entry(&mut self, key: K) -> Entry<K, V> {
match self.search(key.as_ref()) {
Ok(n) => Entry::Occupied(OccupiedEntry{
map: self,
index: n,
}),
Err(n) => Entry::Vacant(VacantEntry{
map: self,
key,
index: n,
})
}
}
pub fn find(&self, key: &str) -> FindResult<&V> {
let (n, found) = match self.search(key) {
Ok(n) => (n, true),
Err(n) => (n, false)
};
let incomplete = self.sequences.get(n + (found as usize))
.map_or(false, |&(ref next, _)| next.as_ref().starts_with(key));
match (found, incomplete) {
(false, false) => FindResult::NotFound,
(false, true) => FindResult::Incomplete,
(true, false) => FindResult::Found(&self.sequences[n].1),
(true, true) => FindResult::Undecided(&self.sequences[n].1),
}
}
pub fn get(&self, key: &str) -> Option<&V> {
match self.search(key) {
Ok(n) => Some(&self.sequences[n].1),
Err(_) => None
}
}
pub fn get_mut(&mut self, key: &str) -> Option<&mut V> {
match self.search(key) {
Ok(n) => Some(&mut self.sequences[n].1),
Err(_) => None
}
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
match self.search(key.as_ref()) {
Ok(n) => Some(replace(&mut self.sequences[n], (key, value)).1),
Err(n) => {
self.sequences.insert(n, (key, value));
None
}
}
}
pub fn remove(&mut self, key: &str) -> Option<(K, V)> {
match self.search(key) {
Ok(n) => Some(self.sequences.remove(n)),
Err(_) => None
}
}
fn search(&self, key: &str) -> Result<usize, usize> {
self.sequences.binary_search_by_key(&key, |&(ref k, _)| &k.as_ref())
}
}
impl<K: AsRef<str>, V> From<Vec<(K, V)>> for SequenceMap<K, V> {
fn from(mut sequences: Vec<(K, V)>) -> SequenceMap<K, V> {
sequences.sort_by(|a, b| a.0.as_ref().cmp(b.0.as_ref()));
sequences.dedup_by(|a, b| a.0.as_ref() == b.0.as_ref());
SequenceMap{sequences}
}
}
impl<K: AsRef<str>, V> FromIterator<(K, V)> for SequenceMap<K, V> {
fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self {
let iter = iter.into_iter();
let mut map = SequenceMap::with_capacity(iter.size_hint().0);
for (k, v) in iter {
map.insert(k, v);
}
map
}
}
pub enum Entry<'a, K: 'a, V: 'a> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
map: &'a mut SequenceMap<K, V>,
index: usize,
}
pub struct VacantEntry<'a, K: 'a, V: 'a> {
map: &'a mut SequenceMap<K, V>,
key: K,
index: usize,
}
impl<'a, K, V> Entry<'a, K, V> {
pub fn and_modify<F: FnOnce(&mut V)>(self, f: F) -> Self {
match self {
Entry::Occupied(mut ent) => {
f(ent.get_mut());
Entry::Occupied(ent)
}
Entry::Vacant(ent) => Entry::Vacant(ent)
}
}
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(ent) => ent.into_mut(),
Entry::Vacant(ent) => ent.insert(default)
}
}
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(ent) => ent.into_mut(),
Entry::Vacant(ent) => ent.insert(default())
}
}
pub fn key(&self) -> &K {
match *self {
Entry::Occupied(ref ent) => ent.key(),
Entry::Vacant(ref ent) => ent.key(),
}
}
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K {
&self.map.sequences[self.index].0
}
pub fn get(&self) -> &V {
&self.map.sequences[self.index].1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.map.sequences[self.index].1
}
pub fn into_mut(self) -> &'a mut V {
&mut self.map.sequences[self.index].1
}
pub fn insert(&mut self, value: V) -> V {
replace(self.get_mut(), value)
}
pub fn remove(self) -> V {
self.map.sequences.remove(self.index).1
}
pub fn remove_entry(self) -> (K, V) {
self.map.sequences.remove(self.index)
}
}
impl<'a, K, V> VacantEntry<'a, K, V> {
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn insert(self, value: V) -> &'a mut V {
self.map.sequences.insert(self.index, (self.key, value));
&mut self.map.sequences[self.index].1
}
}
impl<'a, K: fmt::Debug, V: fmt::Debug> fmt::Debug for Entry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Entry::Occupied(ref ent) =>
f.debug_tuple("Entry")
.field(ent)
.finish(),
Entry::Vacant(ref ent) =>
f.debug_tuple("Entry")
.field(ent)
.finish()
}
}
}
impl<'a, K: fmt::Debug, V: fmt::Debug> fmt::Debug for OccupiedEntry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
impl<'a, K: fmt::Debug, V> fmt::Debug for VacantEntry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("VacantEntry")
.field(self.key())
.finish()
}
}
#[cfg(test)]
mod test {
use super::{FindResult, SequenceMap};
#[test]
fn test_seq_map_get() {
let mut m = SequenceMap::new();
m.insert("ab", 0);
m.insert("ac", 1);
assert_eq!(m.get("a").cloned(), None);
assert_eq!(m.get("aa").cloned(), None);
assert_eq!(m.get("ab").cloned(), Some(0));
assert_eq!(m.get("ac").cloned(), Some(1));
}
#[test]
fn test_seq_map_find() {
let mut m = SequenceMap::new();
m.insert("a", 0);
m.insert("abcd", 1);
m.insert("bcd", 2);
m.insert("bce", 3);
m.insert("cd", 4);
m.insert("cde", 5);
m.insert("cdf", 6);
assert_eq!(m.find("a").cloned(), FindResult::Undecided(0));
assert_eq!(m.find("ab").cloned(), FindResult::Incomplete);
assert_eq!(m.find("abc").cloned(), FindResult::Incomplete);
assert_eq!(m.find("abcd").cloned(), FindResult::Found(1));
assert_eq!(m.find("b").cloned(), FindResult::Incomplete);
assert_eq!(m.find("bc").cloned(), FindResult::Incomplete);
assert_eq!(m.find("bcd").cloned(), FindResult::Found(2));
assert_eq!(m.find("bce").cloned(), FindResult::Found(3));
assert_eq!(m.find("c").cloned(), FindResult::Incomplete);
assert_eq!(m.find("cd").cloned(), FindResult::Undecided(4));
assert_eq!(m.find("cde").cloned(), FindResult::Found(5));
assert_eq!(m.find("cdf").cloned(), FindResult::Found(6));
assert_eq!(m.find("d").cloned(), FindResult::NotFound);
}
#[test]
fn test_seq_map_insert() {
let mut m = SequenceMap::new();
assert_eq!(m.insert("a", 0), None);
assert_eq!(m.insert("b", 1), None);
assert_eq!(m.insert("a", 2), Some(0));
}
#[test]
fn test_seq_map_entry() {
let mut m = SequenceMap::new();
assert_eq!(*m.entry("a").or_insert(0), 0);
assert_eq!(m.get("a").cloned(), Some(0));
assert_eq!(*m.entry("a").or_insert(1), 0);
}
#[test]
fn test_seq_map_from() {
let m: SequenceMap<&'static str, u32> = [
("foo", 0),
("bar", 1),
("baz", 2),
("foo", 3),
].iter().cloned().collect();
assert_eq!(m.sequences(), [
("bar", 1),
("baz", 2),
("foo", 3),
]);
let m = SequenceMap::from(vec![
("foo", 0),
("bar", 1),
("baz", 2),
("foo", 3),
]);
assert_eq!(m.sequences(), [
("bar", 1),
("baz", 2),
("foo", 0),
]);
}
#[test]
fn test_seq_map_types() {
use std::borrow::Cow;
use std::rc::Rc;
use std::sync::Arc;
struct Foo<'a> {
_a: SequenceMap<&'a str, ()>,
_b: SequenceMap<Cow<'a, str>, ()>,
}
let _ = Foo{
_a: SequenceMap::new(),
_b: SequenceMap::new(),
};
SequenceMap::<&'static str, ()>::new();
SequenceMap::<String, ()>::new();
SequenceMap::<Cow<'static, str>, ()>::new();
SequenceMap::<Box<str>, ()>::new();
SequenceMap::<Rc<str>, ()>::new();
SequenceMap::<Arc<str>, ()>::new();
}
}