swiftide_core/
metadata.rs

1//! Metadata is a key-value store for indexation nodes
2//!
3//! Typically metadata is used to extract or generate additional information about the node
4//!
5//! Internally it uses a `BTreeMap` to store the key-value pairs, to ensure the data is sorted.
6use std::collections::{BTreeMap, btree_map::IntoValues};
7
8use serde::Deserializer;
9
10use crate::util::debug_long_utf8;
11
12#[derive(Clone, Default, PartialEq, Eq)]
13pub struct Metadata {
14    inner: BTreeMap<String, serde_json::Value>,
15}
16
17impl std::fmt::Debug for Metadata {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        f.debug_map()
20            .entries(
21                self.inner
22                    .iter()
23                    .map(|(k, v): (&String, &serde_json::Value)| {
24                        let fvalue = v.as_str().map_or_else(
25                            || debug_long_utf8(v.to_string(), 100),
26                            ToString::to_string,
27                        );
28
29                        (k, fvalue)
30                    }),
31            )
32            .finish()
33    }
34}
35
36impl Metadata {
37    pub fn iter(&self) -> impl Iterator<Item = (&String, &serde_json::Value)> {
38        self.inner.iter()
39    }
40
41    pub fn insert<K, V>(&mut self, key: K, value: V)
42    where
43        K: Into<String>,
44        V: Into<serde_json::Value>,
45    {
46        self.inner.insert(key.into(), value.into());
47    }
48
49    pub fn get(&self, key: impl AsRef<str>) -> Option<&serde_json::Value> {
50        self.inner.get(key.as_ref())
51    }
52
53    pub fn into_values(self) -> IntoValues<String, serde_json::Value> {
54        self.inner.into_values()
55    }
56
57    pub fn keys(&self) -> impl Iterator<Item = &str> {
58        self.inner.keys().map(String::as_str)
59    }
60
61    pub fn values(&self) -> impl Iterator<Item = &serde_json::Value> {
62        self.inner.values()
63    }
64
65    pub fn is_empty(&self) -> bool {
66        self.inner.is_empty()
67    }
68}
69
70impl<K, V> Extend<(K, V)> for Metadata
71where
72    K: Into<String>,
73    V: Into<serde_json::Value>,
74{
75    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
76        self.inner
77            .extend(iter.into_iter().map(|(k, v)| (k.into(), v.into())));
78    }
79}
80
81impl<K, V> From<Vec<(K, V)>> for Metadata
82where
83    K: Into<String>,
84    V: Into<serde_json::Value>,
85{
86    fn from(items: Vec<(K, V)>) -> Self {
87        let inner = items
88            .into_iter()
89            .map(|(k, v)| (k.into(), v.into()))
90            .collect();
91        Metadata { inner }
92    }
93}
94
95impl<K, V> From<(K, V)> for Metadata
96where
97    K: Into<String>,
98    V: Into<serde_json::Value>,
99{
100    fn from(items: (K, V)) -> Self {
101        let sliced: [(K, V); 1] = [items];
102        let inner = sliced
103            .into_iter()
104            .map(|(k, v)| (k.into(), v.into()))
105            .collect();
106        Metadata { inner }
107    }
108}
109
110impl<'a, K, V> From<&'a [(K, V)]> for Metadata
111where
112    K: Into<String> + Clone,
113    V: Into<serde_json::Value> + Clone,
114{
115    fn from(items: &'a [(K, V)]) -> Self {
116        let inner = items
117            .iter()
118            .cloned()
119            .map(|(k, v)| (k.into(), v.into()))
120            .collect();
121        Metadata { inner }
122    }
123}
124
125impl<K: Ord, V, const N: usize> From<[(K, V); N]> for Metadata
126where
127    K: Ord + Into<String>,
128    V: Into<serde_json::Value>,
129{
130    fn from(mut arr: [(K, V); N]) -> Self {
131        if N == 0 {
132            return Metadata {
133                inner: BTreeMap::new(),
134            };
135        }
136        arr.sort_by(|a, b| a.0.cmp(&b.0));
137        let inner: BTreeMap<String, serde_json::Value> =
138            arr.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
139        Metadata { inner }
140    }
141}
142
143impl IntoIterator for Metadata {
144    type Item = (String, serde_json::Value);
145    type IntoIter = std::collections::btree_map::IntoIter<String, serde_json::Value>;
146    fn into_iter(self) -> Self::IntoIter {
147        self.inner.into_iter()
148    }
149}
150
151impl<'iter> IntoIterator for &'iter Metadata {
152    type Item = (&'iter String, &'iter serde_json::Value);
153    type IntoIter = std::collections::btree_map::Iter<'iter, String, serde_json::Value>;
154    fn into_iter(self) -> Self::IntoIter {
155        self.inner.iter()
156    }
157}
158
159impl<'de> serde::Deserialize<'de> for Metadata {
160    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
161        BTreeMap::deserialize(deserializer).map(|inner| Metadata { inner })
162    }
163}
164
165impl serde::Serialize for Metadata {
166    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
167        self.inner.serialize(serializer)
168    }
169}
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174    use serde_json::json;
175
176    #[test]
177    fn test_insert_and_get() {
178        let mut metadata = Metadata::default();
179        let key = "key";
180        let value = "value";
181        metadata.insert(key, "value");
182
183        assert_eq!(metadata.get(key).unwrap().as_str(), Some(value));
184    }
185
186    #[test]
187    fn test_iter() {
188        let mut metadata = Metadata::default();
189        metadata.insert("key1", json!("value1"));
190        metadata.insert("key2", json!("value2"));
191
192        let mut iter = metadata.iter();
193        assert_eq!(iter.next(), Some((&"key1".to_string(), &json!("value1"))));
194        assert_eq!(iter.next(), Some((&"key2".to_string(), &json!("value2"))));
195        assert_eq!(iter.next(), None);
196    }
197
198    #[test]
199    fn test_extend() {
200        let mut metadata = Metadata::default();
201        metadata.extend(vec![("key1", json!("value1")), ("key2", json!("value2"))]);
202
203        assert_eq!(metadata.get("key1"), Some(&json!("value1")));
204        assert_eq!(metadata.get("key2"), Some(&json!("value2")));
205    }
206
207    #[test]
208    fn test_from_vec() {
209        let metadata = Metadata::from(vec![("key1", json!("value1")), ("key2", json!("value2"))]);
210
211        assert_eq!(metadata.get("key1"), Some(&json!("value1")));
212        assert_eq!(metadata.get("key2"), Some(&json!("value2")));
213    }
214
215    #[test]
216    fn test_into_values() {
217        let mut metadata = Metadata::default();
218        metadata.insert("key1", json!("value1"));
219        metadata.insert("key2", json!("value2"));
220
221        let values: Vec<_> = metadata.into_values().collect();
222        assert_eq!(values, vec![json!("value1"), json!("value2")]);
223    }
224}