1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::BTreeMap;
4
5#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
6pub struct Metadata {
7 fields: BTreeMap<String, Value>,
8}
9
10impl Metadata {
11 pub fn new() -> Self {
12 Self::default()
13 }
14
15 pub fn insert<V>(&mut self, key: impl Into<String>, value: V)
16 where
17 V: Into<Value>,
18 {
19 self.fields.insert(key.into(), value.into());
20 }
21
22 pub fn get(&self, key: &str) -> Option<&Value> {
23 self.fields.get(key)
24 }
25
26 pub fn fields(&self) -> &BTreeMap<String, Value> {
27 &self.fields
28 }
29
30 pub fn with<V>(mut self, key: impl Into<String>, value: V) -> Self
31 where
32 V: Into<Value>,
33 {
34 self.insert(key, value);
35 self
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::Metadata;
42
43 #[test]
44 fn metadata_stores_values() {
45 let metadata = Metadata::new().with("source", "runbook.md");
46 assert_eq!(metadata.get("source").unwrap(), "runbook.md");
47 }
48
49 #[test]
50 fn metadata_insert_and_fields_expose_values() {
51 let mut metadata = Metadata::new();
52 metadata.insert("retries", 3);
53 metadata.insert("enabled", true);
54
55 assert_eq!(metadata.get("retries").unwrap(), 3);
56 assert_eq!(metadata.fields().len(), 2);
57 assert_eq!(metadata.fields().get("enabled").unwrap(), true);
58 }
59}