qubit_metadata/
metadata.rs1use std::collections::BTreeMap;
13
14use qubit_datatype::{
15 DataType,
16 DataTypeOf,
17};
18use qubit_value::Value;
19use serde::{
20 Deserialize,
21 Serialize,
22};
23
24use crate::{
25 FromMetadataValue,
26 IntoMetadataValue,
27 MetadataError,
28 MetadataResult,
29 MetadataSchema,
30};
31
32#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
42pub struct Metadata(BTreeMap<String, Value>);
43
44impl Metadata {
45 #[inline]
47 #[must_use]
48 pub fn new() -> Self {
49 Self(BTreeMap::new())
50 }
51
52 #[inline]
54 #[must_use]
55 pub fn is_empty(&self) -> bool {
56 self.0.is_empty()
57 }
58
59 #[inline]
61 #[must_use]
62 pub fn len(&self) -> usize {
63 self.0.len()
64 }
65
66 #[inline]
68 #[must_use]
69 pub fn contains_key(&self, key: &str) -> bool {
70 self.0.contains_key(key)
71 }
72
73 #[inline]
78 pub fn get<T>(&self, key: &str) -> Option<T>
79 where
80 T: DataTypeOf + FromMetadataValue,
81 {
82 self.try_get(key).ok()
83 }
84
85 pub fn try_get<T>(&self, key: &str) -> MetadataResult<T>
93 where
94 T: DataTypeOf + FromMetadataValue,
95 {
96 let value = self
97 .0
98 .get(key)
99 .ok_or_else(|| MetadataError::MissingKey(key.to_string()))?;
100 T::from_metadata_value(value).map_err(|error| MetadataError::conversion_error(key, T::DATA_TYPE, value, error))
101 }
102
103 #[inline]
105 #[must_use]
106 pub fn get_raw(&self, key: &str) -> Option<&Value> {
107 self.0.get(key)
108 }
109
110 #[inline]
112 #[must_use]
113 pub fn data_type(&self, key: &str) -> Option<DataType> {
114 self.0.get(key).map(Value::data_type)
115 }
116
117 #[inline]
120 #[must_use]
121 pub fn get_or<T>(&self, key: &str, default: T) -> T
122 where
123 T: DataTypeOf + FromMetadataValue,
124 {
125 self.try_get(key).unwrap_or(default)
126 }
127
128 #[inline]
130 pub fn set<T>(&mut self, key: &str, value: T) -> Option<Value>
131 where
132 T: IntoMetadataValue,
133 {
134 self.0.insert(key.to_string(), value.into_metadata_value())
135 }
136
137 #[inline]
145 pub fn set_checked<T>(&mut self, schema: &MetadataSchema, key: &str, value: T) -> MetadataResult<Option<Value>>
146 where
147 T: IntoMetadataValue,
148 {
149 let value = value.into_metadata_value();
150 schema.validate_entry(key, &value)?;
151 Ok(self.set_raw(key, value))
152 }
153
154 #[inline]
162 pub fn with_checked<T>(mut self, schema: &MetadataSchema, key: &str, value: T) -> MetadataResult<Self>
163 where
164 T: IntoMetadataValue,
165 {
166 self.set_checked(schema, key, value)?;
167 Ok(self)
168 }
169
170 #[inline]
172 #[must_use]
173 pub fn with<T>(mut self, key: &str, value: T) -> Self
174 where
175 T: IntoMetadataValue,
176 {
177 self.set(key, value);
178 self
179 }
180
181 #[inline]
183 pub fn set_raw(&mut self, key: &str, value: Value) -> Option<Value> {
184 self.0.insert(key.to_string(), value)
185 }
186
187 #[inline]
189 #[must_use]
190 pub fn with_raw(mut self, key: &str, value: Value) -> Self {
191 self.set_raw(key, value);
192 self
193 }
194
195 #[inline]
197 pub fn remove(&mut self, key: &str) -> Option<Value> {
198 self.0.remove(key)
199 }
200
201 #[inline]
203 pub fn clear(&mut self) {
204 self.0.clear();
205 }
206
207 #[inline]
209 pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> {
210 self.0.iter().map(|(key, value)| (key.as_str(), value))
211 }
212
213 #[inline]
215 pub fn keys(&self) -> impl Iterator<Item = &str> {
216 self.0.keys().map(String::as_str)
217 }
218
219 #[inline]
221 pub fn values(&self) -> impl Iterator<Item = &Value> {
222 self.0.values()
223 }
224
225 pub fn merge(&mut self, other: Metadata) {
227 for (key, value) in other.0 {
228 self.0.insert(key, value);
229 }
230 }
231
232 #[must_use]
236 pub fn merged(&self, other: &Metadata) -> Metadata {
237 let mut result = self.clone();
238 for (key, value) in &other.0 {
239 result.0.insert(key.clone(), value.clone());
240 }
241 result
242 }
243
244 #[inline]
246 pub fn retain<F>(&mut self, mut predicate: F)
247 where
248 F: FnMut(&str, &Value) -> bool,
249 {
250 self.0.retain(|key, value| predicate(key.as_str(), value));
251 }
252
253 #[inline]
255 #[must_use]
256 pub fn into_inner(self) -> BTreeMap<String, Value> {
257 self.0
258 }
259}
260
261impl From<BTreeMap<String, Value>> for Metadata {
262 #[inline]
263 fn from(map: BTreeMap<String, Value>) -> Self {
264 Self(map)
265 }
266}
267
268impl From<Metadata> for BTreeMap<String, Value> {
269 #[inline]
270 fn from(meta: Metadata) -> Self {
271 meta.0
272 }
273}
274
275impl FromIterator<(String, Value)> for Metadata {
276 #[inline]
277 fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
278 Self(iter.into_iter().collect())
279 }
280}
281
282impl IntoIterator for Metadata {
283 type IntoIter = std::collections::btree_map::IntoIter<String, Value>;
284 type Item = (String, Value);
285
286 #[inline]
287 fn into_iter(self) -> Self::IntoIter {
288 self.0.into_iter()
289 }
290}
291
292impl<'a> IntoIterator for &'a Metadata {
293 type IntoIter = std::collections::btree_map::Iter<'a, String, Value>;
294 type Item = (&'a String, &'a Value);
295
296 #[inline]
297 fn into_iter(self) -> Self::IntoIter {
298 self.0.iter()
299 }
300}
301
302impl Extend<(String, Value)> for Metadata {
303 #[inline]
304 fn extend<I: IntoIterator<Item = (String, Value)>>(&mut self, iter: I) {
305 self.0.extend(iter);
306 }
307}