pub mod authentication;
pub mod electro_optical;
pub mod projection;
pub mod raster;
use crate::{Fields, Result};
use serde::{de::DeserializeOwned, Serialize};
pub use {projection::Projection, raster::Raster};
pub trait Extension: Serialize + DeserializeOwned {
const IDENTIFIER: &'static str;
const PREFIX: &'static str;
fn identifier_prefix() -> &'static str {
assert!(Self::IDENTIFIER.starts_with("https://stac-extensions.github.io/"));
let index = Self::IDENTIFIER["https://stac-extensions.github.io/".len()..]
.find('/')
.expect("all identifiers should have a first path segment");
&Self::IDENTIFIER[0.."https://stac-extensions.github.io/".len() + index + 1]
}
}
pub trait Extensions: Fields {
fn extensions(&self) -> &Vec<String>;
fn extensions_mut(&mut self) -> &mut Vec<String>;
fn has_extension<E: Extension>(&self) -> bool {
self.extensions()
.iter()
.any(|extension| extension.starts_with(E::identifier_prefix()))
}
fn add_extension<E: Extension>(&mut self) {
self.extensions_mut().push(E::IDENTIFIER.to_string());
self.extensions_mut().dedup();
}
fn set_extension<E: Extension>(&mut self, extension: E) -> Result<()> {
self.extensions_mut().push(E::IDENTIFIER.to_string());
self.extensions_mut().dedup();
Fields::set_extension(self, extension)
}
fn remove_extension<E: Extension>(&mut self) {
Fields::remove_extension::<E>(self);
self.extensions_mut()
.retain(|extension| !extension.starts_with(E::identifier_prefix()))
}
}
#[cfg(test)]
mod tests {
use super::Extensions;
use crate::{
extensions::{
raster::{Band, Raster},
Projection,
},
Asset, Extension, Item,
};
use serde_json::json;
#[test]
fn identifer_prefix() {
assert_eq!(
Raster::identifier_prefix(),
"https://stac-extensions.github.io/raster/"
);
assert_eq!(
Projection::identifier_prefix(),
"https://stac-extensions.github.io/projection/"
);
}
#[test]
fn set_extension_on_asset() {
use crate::Fields;
let mut asset = Asset::new("a/href.tif");
let mut band = Band::default();
band.unit = Some("parsecs".to_string());
let raster = Raster { bands: vec![band] };
asset.set_extension(raster).unwrap();
let mut item = Item::new("an-id");
let _ = item.assets.insert("data".to_string(), asset);
}
#[test]
fn remove_extension() {
let mut item = Item::new("an-id");
item.extensions
.push("https://stac-extensions.github.io/projection/v2.0.0/schema.json".to_string());
let _ = item
.properties
.additional_fields
.insert("proj:code".to_string(), json!("EPSG:4326"));
assert!(item.has_extension::<Projection>());
item.remove_extension::<Projection>();
assert!(!item.has_extension::<Projection>());
assert!(item.extensions.is_empty());
assert!(item.properties.additional_fields.is_empty());
}
}