use super::{key::AttributeKeyRef, AttributeKey, AttributeValue};
#[cfg(feature = "rayon")]
use rayon::iter::IntoParallelIterator;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
#[repr(transparent)]
pub struct Attributes(HashMap<AttributeKey, AttributeValue>);
impl<K: Into<AttributeKey>, V: Into<AttributeValue>> From<HashMap<K, V>> for Attributes {
fn from(map: HashMap<K, V>) -> Self {
Attributes(
map.into_iter()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<K: Into<AttributeKey>, V: Into<AttributeValue>, const N: usize> From<[(K, V); N]>
for Attributes
{
fn from(array: [(K, V); N]) -> Self {
Self::from_iter(array)
}
}
impl<K: Into<AttributeKey>, V: Into<AttributeValue>> FromIterator<(K, V)> for Attributes {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
Attributes(
iter.into_iter()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl Default for Attributes {
fn default() -> Self {
Self::new()
}
}
impl Attributes {
pub fn new() -> Self {
Attributes(HashMap::new())
}
pub fn get<'a, K: Into<AttributeKeyRef<'a>>>(&self, key: K) -> Option<&AttributeValue> {
self.0.get(key.into().as_ref())
}
pub fn insert<K: Into<AttributeKey>, V: Into<AttributeValue>>(&mut self, key: K, value: V) {
self.0.insert(key.into(), value.into());
}
pub fn remove<'a, K: Into<AttributeKeyRef<'a>>>(&mut self, key: K) -> Option<AttributeValue> {
self.0.remove(key.into().as_ref())
}
pub fn iter(&self) -> impl Iterator<Item = (&AttributeKey, &AttributeValue)> {
self.0.iter()
}
pub fn keys(&self) -> impl Iterator<Item = &AttributeKey> {
self.0.keys()
}
pub fn attribute_count(&self) -> usize {
self.0.len()
}
}
impl IntoIterator for Attributes {
type Item = (AttributeKey, AttributeValue);
type IntoIter = std::collections::hash_map::IntoIter<AttributeKey, AttributeValue>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl IntoParallelIterator for Attributes {
type Item = (AttributeKey, AttributeValue);
type Iter = rayon::collections::hash_map::IntoIter<AttributeKey, AttributeValue>;
fn into_par_iter(self) -> Self::Iter {
self.0.into_par_iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_attributes_new() {
let attrs = Attributes::new();
assert_eq!(attrs.attribute_count(), 0);
}
#[test]
fn test_attributes_insert() {
let mut attrs = Attributes::new();
attrs.insert("key1", "value1");
assert_eq!(attrs.get("key1"), Some(&AttributeValue::from("value1")));
attrs.insert("key1", "new_value");
assert_eq!(attrs.get("key1"), Some(&AttributeValue::from("new_value")));
}
#[test]
fn test_attributes_remove() {
let mut attrs = Attributes::new();
attrs.insert("key1", "value1");
assert_eq!(attrs.remove("key1"), Some(AttributeValue::from("value1")));
assert_eq!(attrs.get("key1"), None);
}
#[test]
fn test_attributes_iter() {
let mut attrs = Attributes::new();
attrs.insert("key1", "value1");
let mut iter = attrs.iter();
assert_eq!(
iter.next(),
Some((
&AttributeKey::String("key1".to_string()),
&AttributeValue::from("value1")
))
);
assert_eq!(iter.next(), None);
}
#[test]
fn test_attributes_keys() {
let mut attrs = Attributes::new();
attrs.insert("key1", "value1");
let mut iter = attrs.keys();
assert_eq!(iter.next(), Some(&AttributeKey::String("key1".to_string())));
assert_eq!(iter.next(), None);
}
#[test]
fn test_attributes_attribute_count() {
let mut attrs = Attributes::new();
attrs.insert("key1", "value1");
attrs.insert("key2", "value2");
assert_eq!(attrs.attribute_count(), 2);
}
}