1use std::collections::{btree_map::IntoValues, BTreeMap};
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 is_empty(&self) -> bool {
58 self.inner.is_empty()
59 }
60}
61
62impl<K, V> Extend<(K, V)> for Metadata
63where
64 K: Into<String>,
65 V: Into<serde_json::Value>,
66{
67 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
68 self.inner
69 .extend(iter.into_iter().map(|(k, v)| (k.into(), v.into())));
70 }
71}
72
73impl<K, V> From<Vec<(K, V)>> for Metadata
74where
75 K: Into<String>,
76 V: Into<serde_json::Value>,
77{
78 fn from(items: Vec<(K, V)>) -> Self {
79 let inner = items
80 .into_iter()
81 .map(|(k, v)| (k.into(), v.into()))
82 .collect();
83 Metadata { inner }
84 }
85}
86
87impl<K, V> From<(K, V)> for Metadata
88where
89 K: Into<String>,
90 V: Into<serde_json::Value>,
91{
92 fn from(items: (K, V)) -> Self {
93 let sliced: [(K, V); 1] = [items];
94 let inner = sliced
95 .into_iter()
96 .map(|(k, v)| (k.into(), v.into()))
97 .collect();
98 Metadata { inner }
99 }
100}
101
102impl<'a, K, V> From<&'a [(K, V)]> for Metadata
103where
104 K: Into<String> + Clone,
105 V: Into<serde_json::Value> + Clone,
106{
107 fn from(items: &'a [(K, V)]) -> Self {
108 let inner = items
109 .iter()
110 .cloned()
111 .map(|(k, v)| (k.into(), v.into()))
112 .collect();
113 Metadata { inner }
114 }
115}
116
117impl<K: Ord, V, const N: usize> From<[(K, V); N]> for Metadata
118where
119 K: Ord + Into<String>,
120 V: Into<serde_json::Value>,
121{
122 fn from(mut arr: [(K, V); N]) -> Self {
123 if N == 0 {
124 return Metadata {
125 inner: BTreeMap::new(),
126 };
127 }
128 arr.sort_by(|a, b| a.0.cmp(&b.0));
129 let inner: BTreeMap<String, serde_json::Value> =
130 arr.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
131 Metadata { inner }
132 }
133}
134
135impl IntoIterator for Metadata {
136 type Item = (String, serde_json::Value);
137 type IntoIter = std::collections::btree_map::IntoIter<String, serde_json::Value>;
138 fn into_iter(self) -> Self::IntoIter {
139 self.inner.into_iter()
140 }
141}
142
143impl<'iter> IntoIterator for &'iter Metadata {
144 type Item = (&'iter String, &'iter serde_json::Value);
145 type IntoIter = std::collections::btree_map::Iter<'iter, String, serde_json::Value>;
146 fn into_iter(self) -> Self::IntoIter {
147 self.inner.iter()
148 }
149}
150
151impl<'de> serde::Deserialize<'de> for Metadata {
152 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
153 BTreeMap::deserialize(deserializer).map(|inner| Metadata { inner })
154 }
155}
156
157impl serde::Serialize for Metadata {
158 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
159 self.inner.serialize(serializer)
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use serde_json::json;
167
168 #[test]
169 fn test_insert_and_get() {
170 let mut metadata = Metadata::default();
171 let key = "key";
172 let value = "value";
173 metadata.insert(key, "value");
174
175 assert_eq!(metadata.get(key).unwrap().as_str(), Some(value));
176 }
177
178 #[test]
179 fn test_iter() {
180 let mut metadata = Metadata::default();
181 metadata.insert("key1", json!("value1"));
182 metadata.insert("key2", json!("value2"));
183
184 let mut iter = metadata.iter();
185 assert_eq!(iter.next(), Some((&"key1".to_string(), &json!("value1"))));
186 assert_eq!(iter.next(), Some((&"key2".to_string(), &json!("value2"))));
187 assert_eq!(iter.next(), None);
188 }
189
190 #[test]
191 fn test_extend() {
192 let mut metadata = Metadata::default();
193 metadata.extend(vec![("key1", json!("value1")), ("key2", json!("value2"))]);
194
195 assert_eq!(metadata.get("key1"), Some(&json!("value1")));
196 assert_eq!(metadata.get("key2"), Some(&json!("value2")));
197 }
198
199 #[test]
200 fn test_from_vec() {
201 let metadata = Metadata::from(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_into_values() {
209 let mut metadata = Metadata::default();
210 metadata.insert("key1", json!("value1"));
211 metadata.insert("key2", json!("value2"));
212
213 let values: Vec<_> = metadata.into_values().collect();
214 assert_eq!(values, vec![json!("value1"), json!("value2")]);
215 }
216}