use std::borrow::Borrow;
use std::cell::UnsafeCell;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::Hash;
use std::iter::FromIterator;
use super::super::util::ExplicitDebug;
pub type Key = String;
pub type Value = String;
#[derive(Default)]
pub struct Properties {
set: HashSet<Key>,
map: HashMap<Key, Value>,
_marker: UnsafeCell<()>,
}
impl Properties {
#[inline]
pub fn new() -> Self {
Self::default()
}
}
impl Properties {
#[inline]
pub fn contains<K: ?Sized>(&self, k: &K) -> bool
where Key: Borrow<K>, K: Hash + Eq
{
self.set.contains(k) || self.map.contains_key(k)
}
#[inline]
pub fn get_value<'p, K: ?Sized>(&'p self, k: &K) -> Option<&'p Value>
where Key: Borrow<K>, K: Hash + Eq
{
self.map.get(k)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.set.is_empty() && self.map.is_empty()
}
#[inline]
pub fn iter<'p>(&'p self) -> Box<Iterator<Item=(&'p Key, Option<&'p Value>)> + 'p> {
IntoIterator::into_iter(self)
}
#[inline]
pub fn keys<'p>(&'p self) -> Box<Iterator<Item=&'p Key> + 'p> {
Box::new(
self.set.iter().chain(self.map.keys())
)
}
#[inline]
pub fn len(&self) -> usize {
self.set.len() + self.map.len()
}
}
impl Properties {
pub fn clear(&mut self) {
self.set.clear();
self.map.clear();
}
pub fn insert(&mut self, key: Key, opt_value: Option<Value>) -> Option<Option<Value>> {
match opt_value {
Some(value) => self.put_with_value(key, value),
None => self.put(key),
}
}
pub fn iter_mut<'p>(&'p mut self) -> Box<Iterator<Item=(&'p Key, Option<&'p mut Value>)> + 'p> {
Box::new(
self.set.iter().map(|k| (k, None))
.chain(self.map.iter_mut().map(|(k, v)| (k, Some(v))))
)
}
pub fn put(&mut self, key: Key) -> Option<Option<Value>> {
let prev = self.map.remove(&key);
if self.set.insert(key) { Some(prev) } else { None }
}
pub fn put_with_value(&mut self, key: Key, value: Value) -> Option<Option<Value>> {
let was_in_set = self.set.remove(&key);
match self.map.insert(key, value) {
Some(prev) => Some(Some(prev)),
None => if was_in_set { Some(None) } else { None },
}
}
pub fn remove<K: ?Sized>(&mut self, key: &K) -> Option<Option<Value>>
where Key: Borrow<K>, K: Hash + Eq
{
if self.set.remove(key) {
Some(None)
} else {
self.map.remove(key).map(Some)
}
}
}
impl FromIterator<Key> for Properties {
fn from_iter<T: IntoIterator<Item=Key>>(iter: T) -> Self {
Properties{set: iter.into_iter().collect(), ..Properties::default()}
}
}
impl FromIterator<(Key, Value)> for Properties {
fn from_iter<T: IntoIterator<Item=(Key, Value)>>(iter: T) -> Self {
Properties{map: iter.into_iter().collect(), ..Properties::default()}
}
}
impl FromIterator<(Key, Option<Value>)> for Properties {
fn from_iter<T: IntoIterator<Item=(Key, Option<Value>)>>(iter: T) -> Self {
let (map_items, set_items): (Vec<_>, Vec<_>) =
iter.into_iter().partition(|&(_, ref v)| v.is_some());
Properties {
map: map_items.into_iter().map(|(k, v)| (k, v.unwrap())).collect(),
set: set_items.into_iter().map(|(k, _)| k).collect(),
..Properties::default()
}
}
}
impl IntoIterator for Properties {
type Item = (Key, Option<Value>);
type IntoIter = Box<Iterator<Item=Self::Item>>;
fn into_iter(self) -> Self::IntoIter {
Box::new(
self.set.into_iter().map(|p| (p, None))
.chain(self.map.into_iter().map(|(k, v)| (k, Some(v))))
)
}
}
impl<'p> IntoIterator for &'p Properties {
type Item = (&'p Key, Option<&'p Value>);
type IntoIter = Box<Iterator<Item=Self::Item> + 'p>;
fn into_iter(self) -> Self::IntoIter {
Box::new(
self.set.iter().map(|p| (p, None))
.chain(self.map.iter().map(|(k, v)| (k, Some(v))))
)
}
}
impl fmt::Debug for Properties {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_set()
.entries(
self.iter().map(|(k, v)| {
format!("\"{}\"{}", k, v.map(|v| format!(": \"{}\"", v))
.unwrap_or_else(String::new))
})
.map(ExplicitDebug::from))
.finish()
}
}