#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OrderedMap<V> {
entries: Vec<(String, V)>,
}
pub type Values = OrderedMap<String>;
pub type Restrictions = OrderedMap<Vec<String>>;
impl<V> Default for OrderedMap<V> {
fn default() -> Self {
Self::new()
}
}
impl<V> OrderedMap<V> {
#[must_use]
pub const fn new() -> Self {
Self {
entries: Vec::new(),
}
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
fn position(&self, key: &str) -> Option<usize> {
self.entries.iter().position(|(k, _)| k == key)
}
#[must_use]
pub fn get(&self, key: &str) -> Option<&V> {
self.position(key).map(|i| &self.entries[i].1)
}
pub fn get_mut(&mut self, key: &str) -> Option<&mut V> {
self.position(key).map(|i| &mut self.entries[i].1)
}
#[must_use]
pub fn contains_key(&self, key: &str) -> bool {
self.position(key).is_some()
}
pub fn insert(&mut self, key: impl Into<String>, value: V) -> Option<V> {
let key = key.into();
if let Some(i) = self.position(&key) {
return Some(std::mem::replace(&mut self.entries[i].1, value));
}
self.entries.push((key, value));
None
}
pub fn remove(&mut self, key: &str) -> Option<V> {
self.position(key).map(|i| self.entries.remove(i).1)
}
pub fn iter(&self) -> impl ExactSizeIterator<Item = (&str, &V)> {
self.entries.iter().map(|(k, v)| (k.as_str(), v))
}
pub fn keys(&self) -> impl ExactSizeIterator<Item = &str> {
self.entries.iter().map(|(k, _)| k.as_str())
}
}
impl<K: Into<String>, V> FromIterator<(K, V)> for OrderedMap<V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut map = Self::new();
map.extend(iter);
map
}
}
impl<K: Into<String>, V> Extend<(K, V)> for OrderedMap<V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k, v);
}
}
}
impl<V> IntoIterator for OrderedMap<V> {
type Item = (String, V);
type IntoIter = std::vec::IntoIter<(String, V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl<'a, V> IntoIterator for &'a OrderedMap<V> {
type Item = (&'a str, &'a V);
type IntoIter =
std::iter::Map<std::slice::Iter<'a, (String, V)>, fn(&'a (String, V)) -> (&'a str, &'a V)>;
fn into_iter(self) -> Self::IntoIter {
fn split<V>(entry: &(String, V)) -> (&str, &V) {
(entry.0.as_str(), &entry.1)
}
self.entries.iter().map(split)
}
}