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