From 829396846eb7f0ec584766a356a90c61fc11da68 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 24 Dec 2024 17:26:49 +0100 Subject: [PATCH] `astreams`: Yet another attempt at reasonable mapping --- acrate_astreams/Cargo.toml | 8 +- acrate_astreams/src/activitystreams.rs | 6 - acrate_astreams/src/activitystreams/jsonld.rs | 109 ++++++++++++++++++ acrate_astreams/src/activitystreams/mod.rs | 35 ++++++ 4 files changed, 151 insertions(+), 7 deletions(-) delete mode 100644 acrate_astreams/src/activitystreams.rs create mode 100644 acrate_astreams/src/activitystreams/jsonld.rs create mode 100644 acrate_astreams/src/activitystreams/mod.rs diff --git a/acrate_astreams/Cargo.toml b/acrate_astreams/Cargo.toml index 6d24e95..6aed621 100644 --- a/acrate_astreams/Cargo.toml +++ b/acrate_astreams/Cargo.toml @@ -13,12 +13,18 @@ categories = ["web-programming"] iref = "3.2.2" json-ld = { version = "0.21.1", features = ["serde", "reqwest"] } log = "0.4.22" +anyhow = "1.0.95" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" static-iref = "3.0.0" thiserror = "2.0.3" - +mediatype = { version = "0.19.18", features = ["serde"] } +language-tags = { version = "0.3.2", features = ["serde"] } [dev-dependencies] tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] } tokio-test = "0.4.4" + +[lints.clippy] +tabs-in-doc-comments = "allow" +let-and-return = "allow" diff --git a/acrate_astreams/src/activitystreams.rs b/acrate_astreams/src/activitystreams.rs deleted file mode 100644 index ac4fbd7..0000000 --- a/acrate_astreams/src/activitystreams.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Struct definitions for ActivityStreams Core and Extended Types. -//! -//! # Specification -//! -//! - -//! diff --git a/acrate_astreams/src/activitystreams/jsonld.rs b/acrate_astreams/src/activitystreams/jsonld.rs new file mode 100644 index 0000000..5583212 --- /dev/null +++ b/acrate_astreams/src/activitystreams/jsonld.rs @@ -0,0 +1,109 @@ +use anyhow::{anyhow, Error}; +use static_iref::iri; +use anyhow::Result as AResult; +use iref::Iri; +use mediatype::MediaType; +use crate::activitystreams::StreamsLink; + +pub trait StreamsJsonLD { + fn get_one_str(&self, id: &Iri) -> Option>; + fn get_multiple_str(&self, id: &Iri) -> impl Iterator>; + fn get_one_mediatype(&self, id: &Iri) -> Option>; +} + +impl StreamsJsonLD for &json_ld::Node { + fn get_one_str(&self, id: &Iri) -> Option> { + let property = match self.properties.get_any(&id) { + None => return None, + Some(property) => property, + }; + + let value = match property.as_value() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD value"))), + Some(value) => value, + }; + + let r#str = match value.as_str() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD string"))), + Some(string) => string + }; + + let string = r#str.to_string(); + + Some(Ok(string)) + } + + fn get_multiple_str(&self, id: &Iri) -> impl Iterator> { + let properties = self.properties.get(&id); + + let values = properties.map(|v| v + .as_value() + .ok_or(anyhow!("Couldn't process property as JSON-LD value")) + ); + + let strs = values.flat_map(|v| v + .map(|v| v + .as_str() + .ok_or(anyhow!("Couldn't process property as JSON-LD string")) + ) + ); + + let strings = strs.map(|v| v + .map(|v| v + .to_string() + ) + ); + + strings + } + + fn get_one_mediatype(&self, id: &Iri) -> Option> { + let property = match self.properties.get_any(&id) { + None => return None, + Some(property) => property, + }; + + let value = match property.as_value() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD value"))), + Some(value) => value, + }; + + let string = match value.as_str() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD string"))), + Some(string) => string + }; + + let mediatype = match MediaType::parse(string) { + Err(e) => return Some(Err(Error::from(e).context("Couldn't parse property as MIME media type"))), + Ok(mediatype) => mediatype, + }; + + Some(Ok(mediatype)) + } +} + +impl StreamsLink for &json_ld::Node { + fn streams_href(&self) -> Option> { + self.get_one_str( + iri!("https://www.w3.org/ns/activitystreams#href") + ) + } + + fn streams_rel(&self) -> impl Iterator> { + self.get_multiple_str( + iri!("https://www.w3.org/ns/activitystreams#rel") + ) + } + + fn streams_media_type(&self) -> Option> { + self.get_one_mediatype( + iri!("https://www.w3.org/ns/activitystreams#mediaType") + ) + } + + /* + fn streams_name(&self) -> impl Iterator, String)>> { + todo!() + } + */ +} diff --git a/acrate_astreams/src/activitystreams/mod.rs b/acrate_astreams/src/activitystreams/mod.rs new file mode 100644 index 0000000..1646bc9 --- /dev/null +++ b/acrate_astreams/src/activitystreams/mod.rs @@ -0,0 +1,35 @@ +//! Struct definitions for ActivityStreams Core and Extended Types. +//! +//! # Functional +//! +//! > Properties marked as being "Functional" can have only one value. +//! > +//! > Items not marked as "Functional" can have multiple values. +//! +//! # Specification +//! +//! - +//! + +use anyhow::Result as AResult; +use mediatype::MediaType; + +pub mod jsonld; + +/// Something that can be considered a `https://www.w3.org/ns/activitystreams#Object`. +pub trait StreamsObject { + +} + +/// Something that can be considered a `https://www.w3.org/ns/activitystreams#Link`. +pub trait StreamsLink { + fn streams_href(&self) -> Option>; + + fn streams_rel(&self) -> impl Iterator>; + + fn streams_media_type(&self) -> Option>; + + /* + fn streams_name(&self) -> impl Iterator>; + */ +}