token_value_map/
token_value_map.rs

1use crate::*;
2use std::{
3    collections::HashMap,
4    hash::{Hash, Hasher},
5};
6use ustr::Ustr;
7
8/// A collection of named values indexed by string tokens.
9///
10/// [`TokenValueMap`] `struct` stores a mapping from string tokens to [`Value`]
11/// instances, allowing efficient lookup of named parameters or attributes by
12/// token.
13#[derive(Clone, Debug, Default, PartialEq)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct TokenValueMap {
16    attributes: HashMap<Ustr, Value>,
17}
18
19impl Hash for TokenValueMap {
20    fn hash<H: Hasher>(&self, state: &mut H) {
21        self.attributes.len().hash(state);
22        // Note: HashMap iteration order is not deterministic,
23        // so we need to sort for consistent hashing
24        let mut items: Vec<_> = self.attributes.iter().collect();
25        items.sort_by_key(|(k, _)| *k);
26        for (token, value) in items {
27            token.hash(state);
28            value.hash(state);
29        }
30    }
31}
32
33impl TokenValueMap {
34    pub fn new() -> Self {
35        Self::default()
36    }
37
38    pub fn with_capacity(capacity: usize) -> Self {
39        Self {
40            attributes: HashMap::with_capacity(capacity),
41        }
42    }
43
44    pub fn insert<V: Into<Value>>(&mut self, token: impl Into<Ustr>, value: V) {
45        self.attributes.insert(token.into(), value.into());
46    }
47
48    pub fn get(&self, token: &Ustr) -> Option<&Value> {
49        self.attributes.get(token)
50    }
51
52    pub fn get_mut(&mut self, token: &Ustr) -> Option<&mut Value> {
53        self.attributes.get_mut(token)
54    }
55
56    pub fn remove(&mut self, token: &Ustr) -> Option<Value> {
57        self.attributes.remove(token)
58    }
59
60    pub fn contains(&self, token: &Ustr) -> bool {
61        self.attributes.contains_key(token)
62    }
63
64    pub fn len(&self) -> usize {
65        self.attributes.len()
66    }
67
68    pub fn is_empty(&self) -> bool {
69        self.attributes.is_empty()
70    }
71
72    pub fn clear(&mut self) {
73        self.attributes.clear();
74    }
75
76    pub fn iter(&self) -> impl Iterator<Item = (&Ustr, &Value)> {
77        self.attributes.iter()
78    }
79
80    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Ustr, &mut Value)> {
81        self.attributes.iter_mut()
82    }
83
84    pub fn tokens(&self) -> impl Iterator<Item = &Ustr> {
85        self.attributes.keys()
86    }
87
88    pub fn values(&self) -> impl Iterator<Item = &Value> {
89        self.attributes.values()
90    }
91
92    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut Value> {
93        self.attributes.values_mut()
94    }
95
96    pub fn extend<I>(&mut self, iter: I)
97    where
98        I: IntoIterator<Item = (Ustr, Value)>,
99    {
100        self.attributes.extend(iter);
101    }
102
103    pub fn retain<F>(&mut self, mut f: F)
104    where
105        F: FnMut(&Ustr, &Value) -> bool,
106    {
107        self.attributes.retain(|k, v| f(k, v));
108    }
109}
110
111// Manual Eq implementation for TokenValueMap
112// This is safe because we handle floating point comparison deterministically
113impl Eq for TokenValueMap {}
114
115impl FromIterator<(Ustr, Value)> for TokenValueMap {
116    fn from_iter<T: IntoIterator<Item = (Ustr, Value)>>(iter: T) -> Self {
117        Self {
118            attributes: HashMap::from_iter(iter),
119        }
120    }
121}
122
123impl<const N: usize> From<[(Ustr, Value); N]> for TokenValueMap {
124    fn from(arr: [(Ustr, Value); N]) -> Self {
125        Self {
126            attributes: HashMap::from(arr),
127        }
128    }
129}