153 lines
4.6 KiB
Rust
153 lines
4.6 KiB
Rust
use serde::de::Error;
|
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
use serde_json::Value;
|
|
use std::fmt::Debug;
|
|
use std::str::FromStr;
|
|
|
|
pub mod acct;
|
|
pub mod activity_streams;
|
|
|
|
pub trait ContentType: Serialize {
|
|
fn mime_type(&self) -> &'static str;
|
|
}
|
|
|
|
macro_rules! content_type {
|
|
($visib:vis $typ:ident, $expression:expr) => {
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
|
|
$visib struct $typ;
|
|
|
|
impl AsRef<str> for $typ {
|
|
fn as_ref(&self) -> &'static str {
|
|
$expression
|
|
}
|
|
}
|
|
|
|
impl Serialize for $typ {
|
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
serializer.serialize_str($expression)
|
|
}
|
|
}
|
|
|
|
impl ContentType for $typ {
|
|
fn mime_type(&self) -> &'static str {
|
|
$expression
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for $typ {
|
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
let content_type = String::deserialize(deserializer)?;
|
|
|
|
if matches!(content_type.as_ref(), $expression) {
|
|
Ok(Self)
|
|
} else {
|
|
Err(Error::custom(format!(
|
|
"Invalid content type: {content_type}"
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub mod content_type {
|
|
use crate::web_model::ContentType;
|
|
use serde::de::Error;
|
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
|
|
content_type!(pub ContentActivityStreams, "application/activity+json");
|
|
content_type!(pub ContentHtml, "text/html");
|
|
content_type!(pub ContentJson, "application/json");
|
|
content_type!(pub ContentJrdJson, "application/jrd+json");
|
|
content_type!(pub ContentMultipartFormData, "multipart/form-data");
|
|
content_type!(pub ContentUrlEncoded, "application/x-www-form-urlencoded");
|
|
}
|
|
|
|
macro_rules! link_rel {
|
|
($visib:vis $typ:ident, $expression:expr) => {
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
|
|
$visib struct $typ;
|
|
|
|
impl AsRef<str> for $typ {
|
|
fn as_ref(&self) -> &'static str {
|
|
$expression
|
|
}
|
|
}
|
|
|
|
impl Serialize for $typ {
|
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
serializer.serialize_str($expression)
|
|
}
|
|
}
|
|
|
|
impl Rel for $typ {
|
|
fn rel(&self) -> &'static str {
|
|
$expression
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for $typ {
|
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
let rel = String::deserialize(deserializer)?;
|
|
|
|
if matches!(rel.as_ref(), $expression) {
|
|
Ok(Self)
|
|
} else {
|
|
Err(Error::custom(format!(
|
|
"Invalid rel: {rel}"
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub trait Rel: Serialize {
|
|
fn rel(&self) -> &'static str;
|
|
}
|
|
|
|
pub mod rel {
|
|
use crate::web_model::Rel;
|
|
use serde::de::Error;
|
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
|
|
link_rel!(pub RelWebFingerProfilePage, "http://webfinger.net/rel/profile-page");
|
|
link_rel!(pub RelSelf, "self");
|
|
link_rel!(pub RelOStatusSubscribe, "http://ostatus.org/schema/1.0/subscribe");
|
|
link_rel!(pub RelNodeInfo20, "http://nodeinfo.diaspora.software/ns/schema/2.0");
|
|
link_rel!(pub RelNodeInfo21, "http://nodeinfo.diaspora.software/ns/schema/2.1");
|
|
}
|
|
|
|
#[derive(Clone, Eq, PartialEq, Debug)]
|
|
pub struct ListContaining<T: Clone + Eq + PartialEq + Debug + AsRef<str> + FromStr>(pub T);
|
|
|
|
impl<T> Serialize for ListContaining<T>
|
|
where
|
|
T: Clone + Eq + PartialEq + Debug + AsRef<str> + FromStr,
|
|
{
|
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
vec![AsRef::<str>::as_ref(&self.0)].serialize(serializer)
|
|
}
|
|
}
|
|
|
|
impl<'de, T> Deserialize<'de> for ListContaining<T>
|
|
where
|
|
T: Clone + Eq + PartialEq + Debug + AsRef<str> + FromStr,
|
|
{
|
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
let data = Vec::<Value>::deserialize(deserializer)?;
|
|
|
|
let dt = data
|
|
.iter()
|
|
.filter_map(Value::as_str)
|
|
.filter_map(|val| T::from_str(val).ok())
|
|
.next();
|
|
|
|
if let Some(value) = dt {
|
|
Ok(ListContaining(value))
|
|
} else {
|
|
Err(Error::custom("Count not find item in list.".to_string()))
|
|
}
|
|
}
|
|
}
|