qubit_metadata/
metadata.rs1use std::collections::BTreeMap;
13
14use qubit_datatype::{DataType, DataTypeOf};
15use qubit_value::Value;
16use serde::{Deserialize, Serialize};
17
18use crate::{FromMetadataValue, IntoMetadataValue, MetadataError, MetadataResult, MetadataSchema};
19
20#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
30pub struct Metadata(BTreeMap<String, Value>);
31
32impl Metadata {
33 #[inline]
35 #[must_use]
36 pub fn new() -> Self {
37 Self(BTreeMap::new())
38 }
39
40 #[inline]
42 #[must_use]
43 pub fn is_empty(&self) -> bool {
44 self.0.is_empty()
45 }
46
47 #[inline]
49 #[must_use]
50 pub fn len(&self) -> usize {
51 self.0.len()
52 }
53
54 #[inline]
56 #[must_use]
57 pub fn contains_key(&self, key: &str) -> bool {
58 self.0.contains_key(key)
59 }
60
61 #[inline]
66 pub fn get<T>(&self, key: &str) -> Option<T>
67 where
68 T: DataTypeOf + FromMetadataValue,
69 {
70 self.try_get(key).ok()
71 }
72
73 pub fn try_get<T>(&self, key: &str) -> MetadataResult<T>
81 where
82 T: DataTypeOf + FromMetadataValue,
83 {
84 let value = self
85 .0
86 .get(key)
87 .ok_or_else(|| MetadataError::MissingKey(key.to_string()))?;
88 T::from_metadata_value(value)
89 .map_err(|error| MetadataError::conversion_error(key, T::DATA_TYPE, value, error))
90 }
91
92 #[inline]
94 #[must_use]
95 pub fn get_raw(&self, key: &str) -> Option<&Value> {
96 self.0.get(key)
97 }
98
99 #[inline]
101 #[must_use]
102 pub fn data_type(&self, key: &str) -> Option<DataType> {
103 self.0.get(key).map(Value::data_type)
104 }
105
106 #[inline]
109 #[must_use]
110 pub fn get_or<T>(&self, key: &str, default: T) -> T
111 where
112 T: DataTypeOf + FromMetadataValue,
113 {
114 self.try_get(key).unwrap_or(default)
115 }
116
117 #[inline]
119 pub fn set<T>(&mut self, key: &str, value: T) -> Option<Value>
120 where
121 T: IntoMetadataValue,
122 {
123 self.0.insert(key.to_string(), value.into_metadata_value())
124 }
125
126 #[inline]
134 pub fn set_checked<T>(
135 &mut self,
136 schema: &MetadataSchema,
137 key: &str,
138 value: T,
139 ) -> MetadataResult<Option<Value>>
140 where
141 T: IntoMetadataValue,
142 {
143 let value = value.into_metadata_value();
144 schema.validate_entry(key, &value)?;
145 Ok(self.set_raw(key, value))
146 }
147
148 #[inline]
156 pub fn with_checked<T>(
157 mut self,
158 schema: &MetadataSchema,
159 key: &str,
160 value: T,
161 ) -> MetadataResult<Self>
162 where
163 T: IntoMetadataValue,
164 {
165 self.set_checked(schema, key, value)?;
166 Ok(self)
167 }
168
169 #[inline]
171 #[must_use]
172 pub fn with<T>(mut self, key: &str, value: T) -> Self
173 where
174 T: IntoMetadataValue,
175 {
176 self.set(key, value);
177 self
178 }
179
180 #[inline]
182 pub fn set_raw(&mut self, key: &str, value: Value) -> Option<Value> {
183 self.0.insert(key.to_string(), value)
184 }
185
186 #[inline]
188 #[must_use]
189 pub fn with_raw(mut self, key: &str, value: Value) -> Self {
190 self.set_raw(key, value);
191 self
192 }
193
194 #[inline]
196 pub fn remove(&mut self, key: &str) -> Option<Value> {
197 self.0.remove(key)
198 }
199
200 #[inline]
202 pub fn clear(&mut self) {
203 self.0.clear();
204 }
205
206 #[inline]
208 pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> {
209 self.0.iter().map(|(key, value)| (key.as_str(), value))
210 }
211
212 #[inline]
214 pub fn keys(&self) -> impl Iterator<Item = &str> {
215 self.0.keys().map(String::as_str)
216 }
217
218 #[inline]
220 pub fn values(&self) -> impl Iterator<Item = &Value> {
221 self.0.values()
222 }
223
224 pub fn merge(&mut self, other: Metadata) {
226 for (key, value) in other.0 {
227 self.0.insert(key, value);
228 }
229 }
230
231 #[must_use]
235 pub fn merged(&self, other: &Metadata) -> Metadata {
236 let mut result = self.clone();
237 for (key, value) in &other.0 {
238 result.0.insert(key.clone(), value.clone());
239 }
240 result
241 }
242
243 #[inline]
245 pub fn retain<F>(&mut self, mut predicate: F)
246 where
247 F: FnMut(&str, &Value) -> bool,
248 {
249 self.0.retain(|key, value| predicate(key.as_str(), value));
250 }
251
252 #[inline]
254 #[must_use]
255 pub fn into_inner(self) -> BTreeMap<String, Value> {
256 self.0
257 }
258}
259
260impl From<BTreeMap<String, Value>> for Metadata {
261 #[inline]
262 fn from(map: BTreeMap<String, Value>) -> Self {
263 Self(map)
264 }
265}
266
267impl From<Metadata> for BTreeMap<String, Value> {
268 #[inline]
269 fn from(meta: Metadata) -> Self {
270 meta.0
271 }
272}
273
274impl FromIterator<(String, Value)> for Metadata {
275 #[inline]
276 fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
277 Self(iter.into_iter().collect())
278 }
279}
280
281impl IntoIterator for Metadata {
282 type IntoIter = std::collections::btree_map::IntoIter<String, Value>;
283 type Item = (String, Value);
284
285 #[inline]
286 fn into_iter(self) -> Self::IntoIter {
287 self.0.into_iter()
288 }
289}
290
291impl<'a> IntoIterator for &'a Metadata {
292 type IntoIter = std::collections::btree_map::Iter<'a, String, Value>;
293 type Item = (&'a String, &'a Value);
294
295 #[inline]
296 fn into_iter(self) -> Self::IntoIter {
297 self.0.iter()
298 }
299}
300
301impl Extend<(String, Value)> for Metadata {
302 #[inline]
303 fn extend<I: IntoIterator<Item = (String, Value)>>(&mut self, iter: I) {
304 self.0.extend(iter);
305 }
306}