#![doc = include_str!("../README.md")]
use std::collections::BTreeSet;
pub use iref;
use iref::UriBuf;
use serde::{Deserialize, Serialize};
pub use uuid;
use uuid::Uuid;
mod attributes;
pub use attributes::{AttributesBuilder, AttributesParser};
mod traits;
pub use traits::{NestedOrPrefixedRepr, NestedRepr, PrefixedRepr, ZarrConventionImpl};
mod convention;
pub use convention::{Convention, ConventionDefinition};
pub mod registry;
pub use registry::DEFAULT_ZARR_CONVENTION_REGISTRY;
#[cfg(test)]
mod tests;
pub type Attributes = serde_json::Map<String, serde_json::Value>;
#[derive(Debug, Deserialize)]
pub struct ZarrMetadata {
#[serde(default)]
pub attributes: Attributes,
}
#[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq)]
pub enum ConventionId {
Uuid(Uuid),
SchemaUrl(UriBuf),
SpecUrl(UriBuf),
}
impl From<ConventionDefinition> for ConventionId {
fn from(value: ConventionDefinition) -> Self {
value.id_uuid()
}
}
impl From<Convention> for ConventionId {
fn from(value: Convention) -> Self {
if let Some(i) = value.uuid {
Self::Uuid(i)
} else if let Some(i) = value.schema_url {
Self::SchemaUrl(i)
} else if let Some(i) = value.spec_url {
Self::SpecUrl(i)
} else {
unreachable!("one identifier must be defined")
}
}
}
#[derive(Debug, Default, Clone)]
pub struct ZarrConventions {
uuids: BTreeSet<Uuid>,
schema_urls: BTreeSet<UriBuf>,
spec_urls: BTreeSet<UriBuf>,
}
impl ZarrConventions {
const KEY: &'static str = "zarr_conventions";
pub fn from_attributes(attributes: &Attributes) -> serde_json::Result<Self> {
let Some(zc) = attributes.get(Self::KEY) else {
return Ok(ZarrConventions::default());
};
serde_json::from_value(zc.clone())
}
pub fn contains(&self, id: &ConventionId) -> bool {
match id {
ConventionId::Uuid(uuid) => self.uuids.contains(uuid),
ConventionId::SchemaUrl(uri_buf) => self.schema_urls.contains(uri_buf),
ConventionId::SpecUrl(uri_buf) => self.spec_urls.contains(uri_buf),
}
}
}
impl<'de> Deserialize<'de> for ZarrConventions {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let lst: Vec<Convention> = Deserialize::deserialize(deserializer)?;
Ok(lst
.into_iter()
.fold(ZarrConventions::default(), |mut c, item| {
if let Some(uuid) = item.uuid {
c.uuids.insert(uuid);
}
if let Some(schema_url) = item.schema_url {
c.schema_urls.insert(schema_url);
}
if let Some(spec_url) = item.spec_url {
c.spec_urls.insert(spec_url);
}
c
}))
}
}
impl From<Uuid> for ConventionId {
fn from(value: Uuid) -> Self {
Self::Uuid(value)
}
}
pub fn nest_prefixed(prefix: &str, map: &Attributes, out: Attributes) -> serde_json::Value {
serde_json::Value::Object(
map.iter()
.filter_map(|(k, v)| Some((k.strip_prefix(prefix)?.to_string(), v.clone())))
.fold(out, |mut acc, (k, v)| {
acc.insert(k, v);
acc
}),
)
}