Skip to main content

token_value_map/
generic_token_value_map.rs

1//! Generic token-value map that works with any [`DataSystem`].
2
3use crate::{Token, generic_value::GenericValue, traits::DataSystem};
4use std::{
5    collections::HashMap,
6    hash::{Hash, Hasher},
7};
8
9#[cfg(feature = "rkyv")]
10use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14/// A collection of named values indexed by string tokens.
15///
16/// This is the generic version of [`TokenValueMap`](crate::TokenValueMap) that
17/// works with any [`DataSystem`]. Use this when you have a custom data type system.
18///
19/// For the built-in types, use [`TokenValueMap`](crate::TokenValueMap) which is
20/// an alias for `GenericTokenValueMap<Data>`.
21#[derive(Clone, Debug, PartialEq)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23#[cfg_attr(
24    feature = "serde",
25    serde(bound(
26        serialize = "D: Serialize, D::Animated: Serialize",
27        deserialize = "D: Deserialize<'de>, D::Animated: Deserialize<'de>"
28    ))
29)]
30#[cfg_attr(feature = "rkyv", derive(Archive, RkyvSerialize, RkyvDeserialize))]
31pub struct GenericTokenValueMap<D: DataSystem> {
32    attributes: HashMap<Token, GenericValue<D>>,
33}
34
35impl<D: DataSystem> Hash for GenericTokenValueMap<D> {
36    fn hash<H: Hasher>(&self, state: &mut H) {
37        self.attributes.len().hash(state);
38        // HashMap iteration order is not deterministic, so sort for consistent hashing.
39        let mut items: Vec<_> = self.attributes.iter().collect();
40        items.sort_by_key(|(k, _)| *k);
41        for (token, value) in items {
42            token.hash(state);
43            value.hash(state);
44        }
45    }
46}
47
48impl<D: DataSystem> GenericTokenValueMap<D> {
49    /// Creates a new empty map.
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    /// Creates a new map with the specified capacity.
55    pub fn with_capacity(capacity: usize) -> Self {
56        Self {
57            attributes: HashMap::with_capacity(capacity),
58        }
59    }
60
61    /// Inserts a value with the given token.
62    pub fn insert(&mut self, token: impl Into<Token>, value: impl Into<GenericValue<D>>) {
63        self.attributes.insert(token.into(), value.into());
64    }
65
66    /// Gets a reference to the value for a token.
67    pub fn get(&self, token: &Token) -> Option<&GenericValue<D>> {
68        self.attributes.get(token)
69    }
70
71    /// Gets a mutable reference to the value for a token.
72    pub fn get_mut(&mut self, token: &Token) -> Option<&mut GenericValue<D>> {
73        self.attributes.get_mut(token)
74    }
75
76    /// Removes and returns the value for a token.
77    pub fn remove(&mut self, token: &Token) -> Option<GenericValue<D>> {
78        self.attributes.remove(token)
79    }
80
81    /// Returns `true` if the map contains the given token.
82    pub fn contains(&self, token: &Token) -> bool {
83        self.attributes.contains_key(token)
84    }
85
86    /// Returns the number of entries in the map.
87    pub fn len(&self) -> usize {
88        self.attributes.len()
89    }
90
91    /// Returns `true` if the map is empty.
92    pub fn is_empty(&self) -> bool {
93        self.attributes.is_empty()
94    }
95
96    /// Removes all entries from the map.
97    pub fn clear(&mut self) {
98        self.attributes.clear();
99    }
100
101    /// Iterates over all token-value pairs.
102    pub fn iter(&self) -> impl Iterator<Item = (&Token, &GenericValue<D>)> {
103        self.attributes.iter()
104    }
105
106    /// Iterates mutably over all token-value pairs.
107    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Token, &mut GenericValue<D>)> {
108        self.attributes.iter_mut()
109    }
110
111    /// Iterates over all tokens.
112    pub fn tokens(&self) -> impl Iterator<Item = &Token> {
113        self.attributes.keys()
114    }
115
116    /// Iterates over all values.
117    pub fn values(&self) -> impl Iterator<Item = &GenericValue<D>> {
118        self.attributes.values()
119    }
120
121    /// Iterates mutably over all values.
122    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut GenericValue<D>> {
123        self.attributes.values_mut()
124    }
125
126    /// Extends the map with the given iterator.
127    pub fn extend<I>(&mut self, iter: I)
128    where
129        I: IntoIterator<Item = (Token, GenericValue<D>)>,
130    {
131        self.attributes.extend(iter);
132    }
133
134    /// Retains only the entries for which the predicate returns `true`.
135    pub fn retain<F>(&mut self, mut f: F)
136    where
137        F: FnMut(&Token, &GenericValue<D>) -> bool,
138    {
139        self.attributes.retain(|k, v| f(k, v));
140    }
141}
142
143impl<D: DataSystem> Eq for GenericTokenValueMap<D> {}
144
145impl<D: DataSystem> Default for GenericTokenValueMap<D> {
146    fn default() -> Self {
147        Self {
148            attributes: HashMap::new(),
149        }
150    }
151}
152
153impl<D: DataSystem> FromIterator<(Token, GenericValue<D>)> for GenericTokenValueMap<D> {
154    fn from_iter<T: IntoIterator<Item = (Token, GenericValue<D>)>>(iter: T) -> Self {
155        Self {
156            attributes: HashMap::from_iter(iter),
157        }
158    }
159}
160
161impl<D: DataSystem, const N: usize> From<[(Token, GenericValue<D>); N]>
162    for GenericTokenValueMap<D>
163{
164    fn from(arr: [(Token, GenericValue<D>); N]) -> Self {
165        Self {
166            attributes: HashMap::from(arr),
167        }
168    }
169}