stac_types/fields.rs
1use crate::{Error, Result};
2use serde::{de::DeserializeOwned, Serialize};
3use serde_json::{json, Map, Value};
4
5/// Trait for structures that have gettable and settable fields.
6///
7/// # Examples
8///
9/// ```
10/// use stac::{Catalog, Item, Fields};
11///
12/// let mut catalog = Catalog::new("an-id", "a description");
13/// catalog.set_field("foo", "bar");
14/// assert_eq!(catalog.additional_fields.get("foo").unwrap(), "bar");
15///
16/// let mut item = Item::new("an-id");
17/// item.set_field("foo", "bar");
18/// assert_eq!(item.properties.additional_fields.get("foo").unwrap(), "bar");
19/// assert!(item.additional_fields.is_empty());
20/// ```
21pub trait Fields {
22 /// Gets the fields value.
23 ///
24 /// # Examples
25 ///
26 /// ```
27 /// use stac::{Item, Fields};
28 /// let item = Item::new("an-id");
29 /// assert!(item.fields().is_empty());
30 /// ```
31 fn fields(&self) -> &Map<String, Value>;
32
33 /// Gets a mutable reference to the fields value.
34 ///
35 /// # Examples
36 ///
37 /// ```
38 /// use stac::{Item, Fields};
39 /// let mut item = Item::new("an-id");
40 /// item.fields_mut().insert("foo".to_string(), "bar".into());
41 /// ```
42 fn fields_mut(&mut self) -> &mut Map<String, Value>;
43
44 /// Gets the value of a field.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use stac::{Item, Fields};
50 /// let mut item = Item::new("an-id");
51 /// item.set_field("foo", "bar").unwrap();
52 /// assert_eq!(item.properties.additional_fields.get("foo"), item.field("foo"));
53 /// ```
54 fn field(&self, key: &str) -> Option<&Value> {
55 self.fields().get(key)
56 }
57
58 /// Sets the value of a field.
59 ///
60 /// # Examples
61 ///
62 /// ```
63 /// use stac::{Item, Fields};
64 /// let mut item = Item::new("an-id");
65 /// item.set_field("foo", "bar").unwrap();
66 /// assert_eq!(item.properties.additional_fields["foo"], "bar");
67 /// ```
68 fn set_field<S: Serialize>(&mut self, key: impl ToString, value: S) -> Result<Option<Value>> {
69 let value = serde_json::to_value(value)?;
70 Ok(self.fields_mut().insert(key.to_string(), value))
71 }
72
73 /// Gets values with a prefix.
74 ///
75 /// # Examples
76 ///
77 /// ```
78 /// use stac::{Fields, Item};
79 /// use serde_json::Value;
80 ///
81 /// let item: Item = stac::read("examples/extensions-collection/proj-example/proj-example.json").unwrap();
82 /// let projection: Value = item.fields_with_prefix("proj").unwrap();
83 /// ```
84 fn fields_with_prefix<D: DeserializeOwned>(&self, prefix: &str) -> Result<D> {
85 let mut map = Map::new();
86 let prefix = format!("{}:", prefix);
87 for (key, value) in self.fields().iter() {
88 if key.starts_with(&prefix) && key.len() > prefix.len() {
89 let _ = map.insert(key[prefix.len()..].to_string(), value.clone());
90 }
91 }
92 serde_json::from_value(json!(map)).map_err(Error::from)
93 }
94
95 /// Sets values with a prefix.
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// use stac::{Fields, Item};
101 /// use serde_json::json;
102 ///
103 /// let projection = json!({ "code": "EPSG:4326" });
104 /// let mut item = Item::new("an-id");
105 /// item.set_fields_with_prefix("proj", projection);
106 /// ```
107 fn set_fields_with_prefix<S: Serialize>(&mut self, prefix: &str, value: S) -> Result<()> {
108 let value = serde_json::to_value(value)?;
109 if let Value::Object(object) = value {
110 for (key, value) in object.into_iter() {
111 let _ = self.set_field(format!("{}:{}", prefix, key), value);
112 }
113 Ok(())
114 } else {
115 Err(Error::NotAnObject(value))
116 }
117 }
118
119 /// Removes values with a prefix.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use stac::{Fields, Item};
125 ///
126 /// let mut item: Item = stac::read("examples/extensions-collection/proj-example/proj-example.json").unwrap();
127 /// item.remove_fields_with_prefix("proj");
128 /// ```
129 fn remove_fields_with_prefix(&mut self, prefix: &str) {
130 let prefix = format!("{}:", prefix);
131 self.fields_mut()
132 .retain(|key, _| !(key.starts_with(&prefix) && key.len() > prefix.len()));
133 }
134}