magnetar/core/src/web_model/activity_streams/mod.rs

152 lines
3.9 KiB
Rust

use crate::web_model::ListContaining;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::str::FromStr;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub struct ContextActivityStreams;
impl AsRef<str> for ContextActivityStreams {
fn as_ref(&self) -> &'static str {
"https://www.w3.org/ns/activitystreams"
}
}
impl Serialize for ContextActivityStreams {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_ref())
}
}
impl FromStr for ContextActivityStreams {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if matches!(
s,
"https://www.w3.org/ns/activitystreams" | "http://www.w3.org/ns/activitystreams"
) {
Ok(Self)
} else {
Err(format!("Invalid context: {s}"))
}
}
}
impl<'de> Deserialize<'de> for ContextActivityStreams {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let context = String::deserialize(deserializer)?;
ContextActivityStreams::from_str(&context).map_err(Error::custom)
}
}
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Context {
String(ContextActivityStreams),
Object {
#[serde(rename = "@vocab")]
ld_vocab: ContextActivityStreams,
},
List(ListContaining<ContextActivityStreams>),
}
impl Default for Context {
fn default() -> Self {
Context::String(ContextActivityStreams)
}
}
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
struct ActivityStreamsDocument<T> {
#[serde(rename = "@context", default)]
ld_context: Context,
#[serde(flatten)]
data: T,
}
#[cfg(test)]
mod test {
use crate::web_model::activity_streams::{
ActivityStreamsDocument, Context, ContextActivityStreams,
};
use crate::web_model::ListContaining;
use serde_json::json;
#[test]
fn should_parse_context() {
let json = json!({
"@context": "https://www.w3.org/ns/activitystreams",
"some": "stuff"
});
let doc: ActivityStreamsDocument<()> = serde_json::from_value(json).unwrap();
assert_eq!(doc.ld_context, Context::String(ContextActivityStreams));
}
#[test]
fn should_parse_missing_context() {
let json = json!({
"some": "stuff"
});
let doc: ActivityStreamsDocument<()> = serde_json::from_value(json).unwrap();
assert_eq!(doc.ld_context, Context::String(ContextActivityStreams));
}
#[test]
fn should_parse_context_http() {
let json = json!({
"@context": "http://www.w3.org/ns/activitystreams",
"some": "stuff"
});
let doc: ActivityStreamsDocument<()> = serde_json::from_value(json).unwrap();
assert_eq!(doc.ld_context, Context::String(ContextActivityStreams));
}
#[test]
fn should_parse_context_vocab() {
let json = json!({
"@context": {
"@vocab": "https://www.w3.org/ns/activitystreams",
"foo": "bar"
},
"some": "stuff"
});
let doc: ActivityStreamsDocument<()> = serde_json::from_value(json).unwrap();
assert_eq!(
doc.ld_context,
Context::Object {
ld_vocab: ContextActivityStreams
}
);
}
#[test]
fn should_parse_context_array() {
let json = json!({
"@context": [
{
"foo": "bar"
},
"https://www.w3.org/ns/activitystreams",
],
"some": "stuff"
});
let doc: ActivityStreamsDocument<()> = serde_json::from_value(json).unwrap();
assert_eq!(
doc.ld_context,
Context::List(ListContaining(ContextActivityStreams))
);
}
}