1use 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}