qubit_metadata/
metadata.rs1use std::collections::BTreeMap;
12
13use qubit_common::{DataType, DataTypeOf};
14use qubit_value::{Value, ValueConstructor, ValueConverter};
15use serde::{Deserialize, Serialize};
16
17use crate::{MetadataError, MetadataResult};
18
19#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
29pub struct Metadata(BTreeMap<String, Value>);
30
31impl Metadata {
32 #[inline]
34 #[must_use]
35 pub fn new() -> Self {
36 Self(BTreeMap::new())
37 }
38
39 #[inline]
41 #[must_use]
42 pub fn is_empty(&self) -> bool {
43 self.0.is_empty()
44 }
45
46 #[inline]
48 #[must_use]
49 pub fn len(&self) -> usize {
50 self.0.len()
51 }
52
53 #[inline]
55 #[must_use]
56 pub fn contains_key(&self, key: &str) -> bool {
57 self.0.contains_key(key)
58 }
59
60 #[inline]
65 pub fn get<T>(&self, key: &str) -> Option<T>
66 where
67 T: DataTypeOf,
68 Value: ValueConverter<T>,
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,
83 Value: ValueConverter<T>,
84 {
85 let value = self
86 .0
87 .get(key)
88 .ok_or_else(|| MetadataError::MissingKey(key.to_string()))?;
89 value
90 .to::<T>()
91 .map_err(|error| MetadataError::conversion_error(key, T::DATA_TYPE, value, error))
92 }
93
94 #[inline]
96 #[must_use]
97 pub fn get_raw(&self, key: &str) -> Option<&Value> {
98 self.0.get(key)
99 }
100
101 #[inline]
103 #[must_use]
104 pub fn data_type(&self, key: &str) -> Option<DataType> {
105 self.0.get(key).map(Value::data_type)
106 }
107
108 #[inline]
111 #[must_use]
112 pub fn get_or<T>(&self, key: &str, default: T) -> T
113 where
114 T: DataTypeOf,
115 Value: ValueConverter<T>,
116 {
117 self.try_get(key).unwrap_or(default)
118 }
119
120 #[inline]
122 pub fn set<T>(&mut self, key: &str, value: T) -> Option<Value>
123 where
124 Value: ValueConstructor<T>,
125 {
126 self.0.insert(key.to_string(), to_value(value))
127 }
128
129 #[inline]
137 pub fn try_set<T>(&mut self, key: &str, value: T) -> MetadataResult<Option<Value>>
138 where
139 Value: ValueConstructor<T>,
140 {
141 Ok(self.set(key, value))
142 }
143
144 #[inline]
146 #[must_use]
147 pub fn with<T>(mut self, key: &str, value: T) -> Self
148 where
149 Value: ValueConstructor<T>,
150 {
151 self.set(key, value);
152 self
153 }
154
155 #[inline]
157 pub fn set_raw(&mut self, key: &str, value: Value) -> Option<Value> {
158 self.0.insert(key.to_string(), value)
159 }
160
161 #[inline]
163 #[must_use]
164 pub fn with_raw(mut self, key: &str, value: Value) -> Self {
165 self.set_raw(key, value);
166 self
167 }
168
169 #[inline]
171 pub fn remove(&mut self, key: &str) -> Option<Value> {
172 self.0.remove(key)
173 }
174
175 #[inline]
177 pub fn clear(&mut self) {
178 self.0.clear();
179 }
180
181 #[inline]
183 pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> {
184 self.0.iter().map(|(key, value)| (key.as_str(), value))
185 }
186
187 #[inline]
189 pub fn keys(&self) -> impl Iterator<Item = &str> {
190 self.0.keys().map(String::as_str)
191 }
192
193 #[inline]
195 pub fn values(&self) -> impl Iterator<Item = &Value> {
196 self.0.values()
197 }
198
199 pub fn merge(&mut self, other: Metadata) {
201 for (key, value) in other.0 {
202 self.0.insert(key, value);
203 }
204 }
205
206 #[must_use]
210 pub fn merged(&self, other: &Metadata) -> Metadata {
211 let mut result = self.clone();
212 for (key, value) in &other.0 {
213 result.0.insert(key.clone(), value.clone());
214 }
215 result
216 }
217
218 #[inline]
220 pub fn retain<F>(&mut self, mut predicate: F)
221 where
222 F: FnMut(&str, &Value) -> bool,
223 {
224 self.0.retain(|key, value| predicate(key.as_str(), value));
225 }
226
227 #[inline]
229 #[must_use]
230 pub fn into_inner(self) -> BTreeMap<String, Value> {
231 self.0
232 }
233}
234
235#[inline]
236fn to_value<T>(value: T) -> Value
237where
238 Value: ValueConstructor<T>,
239{
240 <Value as ValueConstructor<T>>::from_type(value)
241}
242
243impl From<BTreeMap<String, Value>> for Metadata {
244 #[inline]
245 fn from(map: BTreeMap<String, Value>) -> Self {
246 Self(map)
247 }
248}
249
250impl From<Metadata> for BTreeMap<String, Value> {
251 #[inline]
252 fn from(meta: Metadata) -> Self {
253 meta.0
254 }
255}
256
257impl FromIterator<(String, Value)> for Metadata {
258 #[inline]
259 fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
260 Self(iter.into_iter().collect())
261 }
262}
263
264impl IntoIterator for Metadata {
265 type IntoIter = std::collections::btree_map::IntoIter<String, Value>;
266 type Item = (String, Value);
267
268 #[inline]
269 fn into_iter(self) -> Self::IntoIter {
270 self.0.into_iter()
271 }
272}
273
274impl<'a> IntoIterator for &'a Metadata {
275 type IntoIter = std::collections::btree_map::Iter<'a, String, Value>;
276 type Item = (&'a String, &'a Value);
277
278 #[inline]
279 fn into_iter(self) -> Self::IntoIter {
280 self.0.iter()
281 }
282}
283
284impl Extend<(String, Value)> for Metadata {
285 #[inline]
286 fn extend<I: IntoIterator<Item = (String, Value)>>(&mut self, iter: I) {
287 self.0.extend(iter);
288 }
289}