feat(apb)!: getters return field error

this way we clean upstream code from a lot of .ok_or(), and everything
that doesn't care about the error can go back to previous usage just
adding .ok()
This commit is contained in:
əlemi 2024-06-01 01:04:03 +02:00
parent e7e9584783
commit 40e01fe83b
Signed by: alemi
GPG key ID: A4895B84D311642C
22 changed files with 290 additions and 322 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "apb" name = "apb"
version = "0.1.1" version = "0.2.0"
edition = "2021" edition = "2021"
authors = [ "alemi <me@alemi.dev>" ] authors = [ "alemi <me@alemi.dev>" ]
description = "Traits and types to handle ActivityPub objects" description = "Traits and types to handle ActivityPub objects"

View file

@ -1,7 +1,7 @@
// TODO technically this is not part of ActivityStreams // TODO technically this is not part of ActivityStreams
pub trait PublicKey : super::Base { pub trait PublicKey : super::Base {
fn owner(&self) -> Option<&str> { None } fn owner(&self) -> crate::Field<&str> { Err(crate::FieldErr("owner")) }
fn public_key_pem(&self) -> &str; fn public_key_pem(&self) -> &str;
} }

View file

@ -93,7 +93,6 @@ pub(crate) use macros::{strenum, getter, setter};
mod node; mod node;
pub use node::Node; pub use node::Node;
pub mod server;
pub mod target; pub mod target;
mod key; mod key;
@ -132,6 +131,12 @@ pub use types::{
}, },
}; };
#[derive(Debug, thiserror::Error)]
#[error("missing field '{0}'")]
pub struct FieldErr(pub &'static str);
pub type Field<T> = Result<T, FieldErr>;
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
pub fn new() -> serde_json::Value { pub fn new() -> serde_json::Value {
serde_json::Value::Object(serde_json::Map::default()) serde_json::Value::Object(serde_json::Map::default())

View file

@ -110,101 +110,93 @@ pub(crate) use strenum;
macro_rules! getter { macro_rules! getter {
($name:ident -> type $t:ty) => { ($name:ident -> type $t:ty) => {
fn $name(&self) -> Option<$t> { paste::paste! {
self.get("type")?.as_str()?.try_into().ok() fn [< $name:snake >] (&self) -> $crate::Field<$t> {
} self.get("type")
}; .and_then(|x| x.as_str())
.and_then(|x| x.try_into().ok())
($name:ident -> bool) => { .ok_or($crate::FieldErr("type"))
fn $name(&self) -> Option<bool> {
self.get(stringify!($name))?.as_bool()
}
};
($name:ident -> &str) => {
fn $name(&self) -> Option<&str> {
self.get(stringify!($name))?.as_str()
}
};
($name:ident::$rename:ident -> bool) => {
fn $name(&self) -> Option<bool> {
self.get(stringify!($rename))?.as_bool()
}
};
($name:ident::$rename:ident -> &str) => {
fn $name(&self) -> Option<&str> {
self.get(stringify!($rename))?.as_str()
}
};
($name:ident -> f64) => {
fn $name(&self) -> Option<f64> {
self.get(stringify!($name))?.as_f64()
}
};
($name:ident::$rename:ident -> f64) => {
fn $name(&self) -> Option<f64> {
self.get(stringify!($rename))?.as_f64()
}
};
($name:ident -> u64) => {
fn $name(&self) -> Option<u64> {
self.get(stringify!($name))?.as_u64()
}
};
($name:ident::$rename:ident -> u64) => {
fn $name(&self) -> Option<u64> {
self.get(stringify!($rename))?.as_u64()
}
};
($name:ident -> chrono::DateTime<chrono::Utc>) => {
fn $name(&self) -> Option<chrono::DateTime<chrono::Utc>> {
Some(
chrono::DateTime::parse_from_rfc3339(
self
.get(stringify!($name))?
.as_str()?
)
.ok()?
.with_timezone(&chrono::Utc)
)
}
};
($name:ident::$rename:ident -> chrono::DateTime<chrono::Utc>) => {
fn $name(&self) -> Option<chrono::DateTime<chrono::Utc>> {
Some(
chrono::DateTime::parse_from_rfc3339(
self
.get(stringify!($rename))?
.as_str()?
)
.ok()?
.with_timezone(&chrono::Utc)
)
}
};
($name:ident -> node $t:ty) => {
fn $name(&self) -> $crate::Node<$t> {
match self.get(stringify!($name)) {
Some(x) => $crate::Node::from(x.clone()),
None => $crate::Node::Empty,
} }
} }
}; };
($name:ident::$rename:ident -> node $t:ty) => { ($name:ident -> bool) => {
fn $name(&self) -> $crate::Node<$t> { paste::paste! {
match self.get(stringify!($rename)) { fn [< $name:snake >](&self) -> $crate::Field<bool> {
Some(x) => $crate::Node::from(x.clone()), self.get(stringify!($name))
None => $crate::Node::Empty, .and_then(|x| x.as_bool())
.ok_or($crate::FieldErr(stringify!($name)))
}
}
};
($name:ident -> &str) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Field<&str> {
self.get(stringify!($name))
.and_then(|x| x.as_str())
.ok_or($crate::FieldErr(stringify!($name)))
}
}
};
($name:ident -> f64) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Field<f64> {
self.get(stringify!($name))
.and_then(|x| x.as_f64())
.ok_or($crate::FieldErr(stringify!($name)))
}
}
};
($name:ident -> u64) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Field<u64> {
self.get(stringify!($name))
.and_then(|x| x.as_u64())
.ok_or($crate::FieldErr(stringify!($name)))
}
}
};
($name:ident -> i64) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Field<i64> {
self.get(stringify!($name))
.and_then(|x| x.as_i64())
.ok_or($crate::FieldErr(stringify!($name)))
}
}
};
($name:ident -> chrono::DateTime<chrono::Utc>) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Field<chrono::DateTime<chrono::Utc>> {
Ok(
chrono::DateTime::parse_from_rfc3339(
self
.get(stringify!($name))
.and_then(|x| x.as_str())
.ok_or($crate::FieldErr(stringify!($name)))?
)
.map_err(|e| {
tracing::warn!("invalid time string ({e}), ignoring");
$crate::FieldErr(stringify!($name))
})?
.with_timezone(&chrono::Utc)
)
}
}
};
($name:ident -> node $t:ty) => {
paste::paste! {
fn [< $name:snake >](&self) -> $crate::Node<$t> {
match self.get(stringify!($name)) {
Some(x) => $crate::Node::from(x.clone()),
None => $crate::Node::Empty,
}
} }
} }
}; };
@ -215,7 +207,7 @@ pub(crate) use getter;
macro_rules! setter { macro_rules! setter {
($name:ident -> bool) => { ($name:ident -> bool) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<bool>) -> Self { fn [< set_$name:snake >](mut self, val: Option<bool>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, stringify!($name), val.map(|x| serde_json::Value::Bool(x)) &mut self, stringify!($name), val.map(|x| serde_json::Value::Bool(x))
); );
@ -224,20 +216,9 @@ macro_rules! setter {
} }
}; };
($name:ident::$rename:ident -> bool) => {
paste::item! {
fn [< set_$name >](mut self, val: Option<bool>) -> Self {
$crate::macros::set_maybe_value(
&mut self, stringify!($rename), val.map(|x| serde_json::Value::Bool(x))
);
self
}
}
};
($name:ident -> &str) => { ($name:ident -> &str) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<&str>) -> Self { fn [< set_$name:snake >](mut self, val: Option<&str>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, stringify!($name), val.map(|x| serde_json::Value::String(x.to_string())) &mut self, stringify!($name), val.map(|x| serde_json::Value::String(x.to_string()))
); );
@ -246,20 +227,9 @@ macro_rules! setter {
} }
}; };
($name:ident::$rename:ident -> &str) => {
paste::item! {
fn [< set_$name >](mut self, val: Option<&str>) -> Self {
$crate::macros::set_maybe_value(
&mut self, stringify!($rename), val.map(|x| serde_json::Value::String(x.to_string()))
);
self
}
}
};
($name:ident -> u64) => { ($name:ident -> u64) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<u64>) -> Self { fn [< set_$name:snake >](mut self, val: Option<u64>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, stringify!($name), val.map(|x| serde_json::Value::Number(serde_json::Number::from(x))) &mut self, stringify!($name), val.map(|x| serde_json::Value::Number(serde_json::Number::from(x)))
); );
@ -268,11 +238,11 @@ macro_rules! setter {
} }
}; };
($name:ident::$rename:ident -> u64) => { ($name:ident -> i64) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<u64>) -> Self { fn [< set_$name:snake >](mut self, val: Option<i64>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, stringify!($rename), val.map(|x| serde_json::Value::Number(serde_json::Number::from(x))) &mut self, stringify!($name), val.map(|x| serde_json::Value::Number(serde_json::Number::from(x)))
); );
self self
} }
@ -281,7 +251,7 @@ macro_rules! setter {
($name:ident -> chrono::DateTime<chrono::Utc>) => { ($name:ident -> chrono::DateTime<chrono::Utc>) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> Self { fn [< set_$name:snake >](mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, stringify!($name), val.map(|x| serde_json::Value::String(x.to_rfc3339())) &mut self, stringify!($name), val.map(|x| serde_json::Value::String(x.to_rfc3339()))
); );
@ -290,20 +260,9 @@ macro_rules! setter {
} }
}; };
($name:ident::$rename:ident -> chrono::DateTime<chrono::Utc>) => {
paste::item! {
fn [< set_$name >](mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> Self {
$crate::macros::set_maybe_value(
&mut self, stringify!($rename), val.map(|x| serde_json::Value::String(x.to_rfc3339()))
);
self
}
}
};
($name:ident -> node $t:ty ) => { ($name:ident -> node $t:ty ) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: $crate::Node<$t>) -> Self { fn [< set_$name:snake >](mut self, val: $crate::Node<$t>) -> Self {
$crate::macros::set_maybe_node( $crate::macros::set_maybe_node(
&mut self, stringify!($name), val &mut self, stringify!($name), val
); );
@ -314,7 +273,7 @@ macro_rules! setter {
($name:ident::$rename:ident -> node $t:ty ) => { ($name:ident::$rename:ident -> node $t:ty ) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: $crate::Node<$t>) -> Self { fn [< set_$name:snake >](mut self, val: $crate::Node<$t>) -> Self {
$crate::macros::set_maybe_node( $crate::macros::set_maybe_node(
&mut self, stringify!($rename), val &mut self, stringify!($rename), val
); );
@ -325,7 +284,7 @@ macro_rules! setter {
($name:ident -> type $t:ty ) => { ($name:ident -> type $t:ty ) => {
paste::item! { paste::item! {
fn [< set_$name >](mut self, val: Option<$t>) -> Self { fn [< set_$name:snake >](mut self, val: Option<$t>) -> Self {
$crate::macros::set_maybe_value( $crate::macros::set_maybe_value(
&mut self, "type", val.map(|x| serde_json::Value::String(x.as_ref().to_string())) &mut self, "type", val.map(|x| serde_json::Value::String(x.as_ref().to_string()))
); );

View file

@ -104,7 +104,7 @@ impl<T : super::Base> Node<T> {
match self { match self {
Node::Empty => None, Node::Empty => None,
Node::Link(uri) => Some(uri.href().to_string()), Node::Link(uri) => Some(uri.href().to_string()),
Node::Object(obj) => Some(obj.id()?.to_string()), Node::Object(obj) => Some(obj.id().ok()?.to_string()),
Node::Array(arr) => Some(arr.front()?.id()?.to_string()), Node::Array(arr) => Some(arr.front()?.id()?.to_string()),
} }
} }

View file

@ -1,33 +0,0 @@
#[async_trait::async_trait]
pub trait Outbox {
type Object: crate::Object;
type Activity: crate::Activity;
type Error: std::error::Error;
async fn create_note(&self, uid: String, object: Self::Object) -> Result<String, Self::Error>;
async fn create(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn like(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn follow(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn announce(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn accept(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn reject(&self, _uid: String, _activity: Self::Activity) -> Result<String, Self::Error>;
async fn undo(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn delete(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
async fn update(&self, uid: String, activity: Self::Activity) -> Result<String, Self::Error>;
}
#[async_trait::async_trait]
pub trait Inbox {
type Activity: crate::Activity;
type Error: std::error::Error;
async fn create(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn like(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn follow(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn announce(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn accept(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn reject(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn undo(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn delete(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
async fn update(&self, server: String, activity: Self::Activity) -> Result<(), Self::Error>;
}

View file

@ -3,7 +3,11 @@ use crate::Object;
pub const PUBLIC : &str = "https://www.w3.org/ns/activitystreams#Public"; pub const PUBLIC : &str = "https://www.w3.org/ns/activitystreams#Public";
pub trait Addressed { pub trait Addressed {
fn addressed(&self) -> Vec<String>; fn addressed(&self) -> Vec<String>; // TODO rename this? remate others? idk
fn primary_targets(&self) -> Vec<String>;
fn secondary_targets(&self) -> Vec<String>;
fn public_targets(&self) -> Vec<String>;
fn private_targets(&self) -> Vec<String>;
} }
impl<T: Object> Addressed for T { impl<T: Object> Addressed for T {
@ -14,4 +18,28 @@ impl<T: Object> Addressed for T {
to.append(&mut self.bcc().ids()); to.append(&mut self.bcc().ids());
to to
} }
fn primary_targets(&self) -> Vec<String> {
let mut to : Vec<String> = self.to().ids();
to.append(&mut self.bto().ids());
to
}
fn secondary_targets(&self) -> Vec<String> {
let mut to : Vec<String> = self.cc().ids();
to.append(&mut self.bcc().ids());
to
}
fn public_targets(&self) -> Vec<String> {
let mut to : Vec<String> = self.to().ids();
to.append(&mut self.cc().ids());
to
}
fn private_targets(&self) -> Vec<String> {
let mut to : Vec<String> = self.bto().ids();
to.append(&mut self.bcc().ids());
to
}
} }

View file

@ -9,8 +9,8 @@ crate::strenum! {
} }
pub trait Base : crate::macros::MaybeSend { pub trait Base : crate::macros::MaybeSend {
fn id(&self) -> Option<&str> { None } fn id(&self) -> crate::Field<&str> { Err(crate::FieldErr("id")) }
fn base_type(&self) -> Option<BaseType> { None } fn base_type(&self) -> crate::Field<BaseType> { Err(crate::FieldErr("type")) }
} }
@ -21,30 +21,35 @@ pub trait BaseMut : crate::macros::MaybeSend {
impl Base for String { impl Base for String {
fn id(&self) -> Option<&str> { fn id(&self) -> crate::Field<&str> {
Some(self) Ok(self)
} }
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> crate::Field<BaseType> {
Some(BaseType::Link(LinkType::Link)) Ok(BaseType::Link(LinkType::Link))
} }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl Base for serde_json::Value { impl Base for serde_json::Value {
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> crate::Field<BaseType> {
if self.is_string() { if self.is_string() {
Some(BaseType::Link(LinkType::Link)) Ok(BaseType::Link(LinkType::Link))
} else { } else {
self.get("type")?.as_str()?.try_into().ok() self.get("type")
.and_then(|x| x.as_str())
.and_then(|x| x.try_into().ok())
.ok_or(crate::FieldErr("type"))
} }
} }
fn id(&self) -> Option<&str> { fn id(&self) -> crate::Field<&str> {
if self.is_string() { if self.is_string() {
self.as_str() Ok(self.as_str().ok_or(crate::FieldErr("id"))?)
} else { } else {
self.get("id").map(|x| x.as_str())? self.get("id")
.and_then(|x| x.as_str())
.ok_or(crate::FieldErr("id"))
} }
} }
} }

View file

@ -1,3 +1,5 @@
use crate::{Field, FieldErr};
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::strenum! { crate::strenum! {
pub enum LinkType { pub enum LinkType {
@ -17,24 +19,24 @@ crate::strenum! {
pub trait Link : crate::Base { pub trait Link : crate::Base {
fn href(&self) -> &str; fn href(&self) -> &str;
fn rel(&self) -> Option<&str> { None } fn rel(&self) -> Field<&str> { Err(FieldErr("rel")) }
fn link_media_type(&self) -> Option<&str> { None } // also in obj fn media_type(&self) -> Field<&str> { Err(FieldErr("mediaType")) } // also in obj
fn link_name(&self) -> Option<&str> { None } // also in obj fn name(&self) -> Field<&str> { Err(FieldErr("name")) } // also in obj
fn hreflang(&self) -> Option<&str> { None } fn hreflang(&self) -> Field<&str> { Err(FieldErr("hreflang")) }
fn height(&self) -> Option<u64> { None } fn height(&self) -> Field<u64> { Err(FieldErr("height")) }
fn width(&self) -> Option<u64> { None } fn width(&self) -> Field<u64> { Err(FieldErr("width")) }
fn link_preview(&self) -> Option<&str> { None } // also in obj fn preview(&self) -> Field<&str> { Err(FieldErr("linkPreview")) } // also in obj
} }
pub trait LinkMut : crate::BaseMut { pub trait LinkMut : crate::BaseMut {
fn set_href(self, href: &str) -> Self; fn set_href(self, href: &str) -> Self;
fn set_rel(self, val: Option<&str>) -> Self; fn set_rel(self, val: Option<&str>) -> Self;
fn set_link_media_type(self, val: Option<&str>) -> Self; // also in obj fn set_media_type(self, val: Option<&str>) -> Self; // also in obj
fn set_link_name(self, val: Option<&str>) -> Self; // also in obj fn set_name(self, val: Option<&str>) -> Self; // also in obj
fn set_hreflang(self, val: Option<&str>) -> Self; fn set_hreflang(self, val: Option<&str>) -> Self;
fn set_height(self, val: Option<u64>) -> Self; fn set_height(self, val: Option<u64>) -> Self;
fn set_width(self, val: Option<u64>) -> Self; fn set_width(self, val: Option<u64>) -> Self;
fn set_link_preview(self, val: Option<&str>) -> Self; // also in obj fn set_preview(self, val: Option<&str>) -> Self; // also in obj
} }
impl Link for String { impl Link for String {
@ -55,12 +57,12 @@ impl Link for serde_json::Value {
} }
crate::getter! { rel -> &str } crate::getter! { rel -> &str }
crate::getter! { link_media_type::mediaType -> &str } crate::getter! { mediaType -> &str }
crate::getter! { link_name::name -> &str } crate::getter! { name -> &str }
crate::getter! { hreflang -> &str } crate::getter! { hreflang -> &str }
crate::getter! { height -> u64 } crate::getter! { height -> u64 }
crate::getter! { width -> u64 } crate::getter! { width -> u64 }
crate::getter! { link_preview::preview -> &str } crate::getter! { preview -> &str }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
@ -79,10 +81,10 @@ impl LinkMut for serde_json::Value {
} }
crate::setter! { rel -> &str } crate::setter! { rel -> &str }
crate::setter! { link_media_type::mediaType -> &str } crate::setter! { mediaType -> &str }
crate::setter! { link_name::name -> &str } crate::setter! { name -> &str }
crate::setter! { hreflang -> &str } crate::setter! { hreflang -> &str }
crate::setter! { height -> u64 } crate::setter! { height -> u64 }
crate::setter! { width -> u64 } crate::setter! { width -> u64 }
crate::setter! { link_preview::preview -> &str } crate::setter! { preview -> &str }
} }

View file

@ -8,7 +8,7 @@ strenum! {
} }
pub trait Accept : super::Activity { pub trait Accept : super::Activity {
fn accept_type(&self) -> Option<AcceptType> { None } fn accept_type(&self) -> crate::Field<AcceptType> { Err(crate::FieldErr("type")) }
} }
pub trait AcceptMut : super::ActivityMut { pub trait AcceptMut : super::ActivityMut {

View file

@ -8,7 +8,7 @@ strenum! {
} }
pub trait Ignore : super::Activity { pub trait Ignore : super::Activity {
fn ignore_type(&self) -> Option<IgnoreType> { None } fn ignore_type(&self) -> crate::Field<IgnoreType> { Err(crate::FieldErr("type")) }
} }
pub trait IgnoreMut : super::ActivityMut { pub trait IgnoreMut : super::ActivityMut {

View file

@ -10,7 +10,7 @@ strenum! {
} }
pub trait IntransitiveActivity : super::Activity { pub trait IntransitiveActivity : super::Activity {
fn intransitive_activity_type(&self) -> Option<IntransitiveActivityType> { None } fn intransitive_activity_type(&self) -> crate::Field<IntransitiveActivityType> { Err(crate::FieldErr("type")) }
} }
pub trait IntransitiveActivityMut : super::ActivityMut { pub trait IntransitiveActivityMut : super::ActivityMut {

View file

@ -4,7 +4,7 @@ pub mod intransitive;
pub mod offer; pub mod offer;
pub mod reject; pub mod reject;
use crate::{Node, Object, ObjectMut}; use crate::{Field, FieldErr, Node, Object, ObjectMut};
use accept::AcceptType; use accept::AcceptType;
use reject::RejectType; use reject::RejectType;
use offer::OfferType; use offer::OfferType;
@ -73,7 +73,7 @@ crate::strenum! {
} }
pub trait Activity : Object { pub trait Activity : Object {
fn activity_type(&self) -> Option<ActivityType> { None } fn activity_type(&self) -> Field<ActivityType> { Err(FieldErr("type")) }
fn actor(&self) -> Node<Self::Actor> { Node::Empty } fn actor(&self) -> Node<Self::Actor> { Node::Empty }
fn object(&self) -> Node<Self::Object> { Node::Empty } fn object(&self) -> Node<Self::Object> { Node::Empty }
fn target(&self) -> Node<Self::Object> { Node::Empty } fn target(&self) -> Node<Self::Object> { Node::Empty }

View file

@ -8,7 +8,7 @@ strenum! {
} }
pub trait Offer : super::Activity { pub trait Offer : super::Activity {
fn offer_type(&self) -> Option<OfferType> { None } fn offer_type(&self) -> crate::Field<OfferType> { Err(crate::FieldErr("type")) }
} }
pub trait OfferMut : super::ActivityMut { pub trait OfferMut : super::ActivityMut {

View file

@ -8,7 +8,7 @@ strenum! {
} }
pub trait Reject : super::Activity { pub trait Reject : super::Activity {
fn reject_type(&self) -> Option<RejectType> { None } fn reject_type(&self) -> crate::Field<RejectType> { Err(crate::FieldErr("type")) }
} }
pub trait RejectMut : super::ActivityMut { pub trait RejectMut : super::ActivityMut {

View file

@ -1,4 +1,4 @@
use crate::{Node, Object, ObjectMut}; use crate::{Field, FieldErr, Node, Object, ObjectMut};
crate::strenum! { crate::strenum! {
pub enum ActorType { pub enum ActorType {
@ -14,8 +14,8 @@ pub trait Actor : Object {
type PublicKey : crate::PublicKey; type PublicKey : crate::PublicKey;
type Endpoints : Endpoints; type Endpoints : Endpoints;
fn actor_type(&self) -> Option<ActorType> { None } fn actor_type(&self) -> Field<ActorType> { Err(FieldErr("type")) }
fn preferred_username(&self) -> Option<&str> { None } fn preferred_username(&self) -> Field<&str> { Err(FieldErr("preferredUsername")) }
fn inbox(&self) -> Node<Self::Collection>; fn inbox(&self) -> Node<Self::Collection>;
fn outbox(&self) -> Node<Self::Collection>; fn outbox(&self) -> Node<Self::Collection>;
fn following(&self) -> Node<Self::Collection> { Node::Empty } fn following(&self) -> Node<Self::Collection> { Node::Empty }
@ -28,37 +28,37 @@ pub trait Actor : Object {
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
fn moved_to(&self) -> Node<Self::Actor> { Node::Empty } fn moved_to(&self) -> Node<Self::Actor> { Node::Empty }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
fn manually_approves_followers(&self) -> Option<bool> { None } fn manually_approves_followers(&self) -> Field<bool> { Err(FieldErr("manuallyApprovesFollowers")) }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
fn following_me(&self) -> Option<bool> { None } fn following_me(&self) -> Field<bool> { Err(FieldErr("followingMe")) }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
fn followed_by_me(&self) -> Option<bool> { None } fn followed_by_me(&self) -> Field<bool> { Err(FieldErr("followedByMe")) }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
fn followers_count(&self) -> Option<u64> { None } fn followers_count(&self) -> Field<u64> { Err(FieldErr("followersCount")) }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
fn following_count(&self) -> Option<u64> { None } fn following_count(&self) -> Field<u64> { Err(FieldErr("followingCount")) }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
fn statuses_count(&self) -> Option<u64> { None } fn statuses_count(&self) -> Field<u64> { Err(FieldErr("statusesCount")) }
#[cfg(feature = "toot")] #[cfg(feature = "toot")]
fn discoverable(&self) -> Option<bool> { None } fn discoverable(&self) -> Field<bool> { Err(FieldErr("discoverable")) }
} }
pub trait Endpoints : Object { pub trait Endpoints : Object {
/// Endpoint URI so this actor's clients may access remote ActivityStreams objects which require authentication to access. To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value being the id of the requested ActivityStreams object. /// Endpoint URI so this actor's clients may access remote ActivityStreams objects which require authentication to access. To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value being the id of the requested ActivityStreams object.
fn proxy_url(&self) -> Option<&str> { None } fn proxy_url(&self) -> Field<&str> { Err(FieldErr("proxyUrl")) }
/// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a browser-authenticated user may obtain a new authorization grant. /// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a browser-authenticated user may obtain a new authorization grant.
fn oauth_authorization_endpoint(&self) -> Option<&str> { None } fn oauth_authorization_endpoint(&self) -> Field<&str> { Err(FieldErr("oauthAuthorizationEndpoint")) }
/// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a client may acquire an access token. /// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a client may acquire an access token.
fn oauth_token_endpoint(&self) -> Option<&str> { None } fn oauth_token_endpoint(&self) -> Field<&str> { Err(FieldErr("oauthTokenEndpoint")) }
/// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which browser-authenticated users may authorize a client's public key for client to server interactions. /// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which browser-authenticated users may authorize a client's public key for client to server interactions.
fn provide_client_key(&self) -> Option<&str> { None } fn provide_client_key(&self) -> Field<&str> { Err(FieldErr("provideClientKey")) }
/// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which a client key may be signed by the actor's key for a time window to act on behalf of the actor in interacting with foreign servers. /// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which a client key may be signed by the actor's key for a time window to act on behalf of the actor in interacting with foreign servers.
fn sign_client_key(&self) -> Option<&str> { None } fn sign_client_key(&self) -> Field<&str> { Err(FieldErr("signClientKey")) }
/// An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint. /// An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
fn shared_inbox(&self) -> Option<&str> { None } fn shared_inbox(&self) -> Field<&str> { Err(FieldErr("sharedInbox")) }
} }
pub trait ActorMut : ObjectMut { pub trait ActorMut : ObjectMut {
@ -117,33 +117,33 @@ impl Actor for serde_json::Value {
type PublicKey = serde_json::Value; type PublicKey = serde_json::Value;
type Endpoints = serde_json::Value; type Endpoints = serde_json::Value;
crate::getter! { actor_type -> type ActorType } crate::getter! { actorType -> type ActorType }
crate::getter! { preferred_username::preferredUsername -> &str } crate::getter! { preferredUsername -> &str }
crate::getter! { inbox -> node Self::Collection } crate::getter! { inbox -> node Self::Collection }
crate::getter! { outbox -> node Self::Collection } crate::getter! { outbox -> node Self::Collection }
crate::getter! { following -> node Self::Collection } crate::getter! { following -> node Self::Collection }
crate::getter! { followers -> node Self::Collection } crate::getter! { followers -> node Self::Collection }
crate::getter! { liked -> node Self::Collection } crate::getter! { liked -> node Self::Collection }
crate::getter! { streams -> node Self::Collection } crate::getter! { streams -> node Self::Collection }
crate::getter! { public_key::publicKey -> node Self::PublicKey } crate::getter! { publicKey -> node Self::PublicKey }
crate::getter! { endpoints -> node Self::Endpoints } crate::getter! { endpoints -> node Self::Endpoints }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::getter! { moved_to::movedTo -> node Self::Actor } crate::getter! { movedTo -> node Self::Actor }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::getter! { manually_approves_followers::manuallyApprovedFollowers -> bool } crate::getter! { manuallyApprovesFollowers -> bool }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::getter! { following_me::followingMe -> bool } crate::getter! { followingMe -> bool }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::getter! { followed_by_me::followedByMe -> bool } crate::getter! { followedByMe -> bool }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::getter! { following_count::followingCount -> u64 } crate::getter! { followingCount -> u64 }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::getter! { followers_count::followersCount -> u64 } crate::getter! { followersCount -> u64 }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::getter! { statuses_count::statusesCount -> u64 } crate::getter! { statusesCount -> u64 }
#[cfg(feature = "toot")] #[cfg(feature = "toot")]
crate::getter! { discoverable -> bool } crate::getter! { discoverable -> bool }
@ -151,12 +151,12 @@ impl Actor for serde_json::Value {
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl Endpoints for serde_json::Value { impl Endpoints for serde_json::Value {
crate::getter! { proxy_url::proxyUrl -> &str } crate::getter! { proxyUrl -> &str }
crate::getter! { oauth_authorization_endpoint::oauthAuthorizationEndpoint -> &str } crate::getter! { oauthAuthorizationEndpoint -> &str }
crate::getter! { oauth_token_endpoint::oauthTokenEndpoint -> &str } crate::getter! { oauthTokenEndpoint -> &str }
crate::getter! { provide_client_key::provideClientKey -> &str } crate::getter! { provideClientKey -> &str }
crate::getter! { sign_client_key::signClientKey -> &str } crate::getter! { signClientKey -> &str }
crate::getter! { shared_inbox::sharedInbox -> &str } crate::getter! { sharedInbox -> &str }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
@ -165,32 +165,32 @@ impl ActorMut for serde_json::Value {
type Endpoints = serde_json::Value; type Endpoints = serde_json::Value;
crate::setter! { actor_type -> type ActorType } crate::setter! { actor_type -> type ActorType }
crate::setter! { preferred_username::preferredUsername -> &str } crate::setter! { preferredUsername -> &str }
crate::setter! { inbox -> node Self::Collection } crate::setter! { inbox -> node Self::Collection }
crate::setter! { outbox -> node Self::Collection } crate::setter! { outbox -> node Self::Collection }
crate::setter! { following -> node Self::Collection } crate::setter! { following -> node Self::Collection }
crate::setter! { followers -> node Self::Collection } crate::setter! { followers -> node Self::Collection }
crate::setter! { liked -> node Self::Collection } crate::setter! { liked -> node Self::Collection }
crate::setter! { streams -> node Self::Collection } crate::setter! { streams -> node Self::Collection }
crate::setter! { public_key::publicKey -> node Self::PublicKey } crate::setter! { publicKey -> node Self::PublicKey }
crate::setter! { endpoints -> node Self::Endpoints } crate::setter! { endpoints -> node Self::Endpoints }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::setter! { moved_to::movedTo -> node Self::Actor } crate::setter! { movedTo -> node Self::Actor }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::setter! { manually_approves_followers::manuallyApprovedFollowers -> bool } crate::setter! { manuallyApprovesFollowers -> bool }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::setter! { following_me::followingMe -> bool } crate::setter! { followingMe -> bool }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::setter! { followed_by_me::followedByMe -> bool } crate::setter! { followedByMe -> bool }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::setter! { following_count::followingCount -> u64 } crate::setter! { followingCount -> u64 }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::setter! { followers_count::followersCount -> u64 } crate::setter! { followersCount -> u64 }
#[cfg(feature = "activitypub-counters")] #[cfg(feature = "activitypub-counters")]
crate::setter! { statuses_count::statusesCount -> u64 } crate::setter! { statusesCount -> u64 }
#[cfg(feature = "toot")] #[cfg(feature = "toot")]
crate::setter! { discoverable -> bool } crate::setter! { discoverable -> bool }
@ -198,10 +198,10 @@ impl ActorMut for serde_json::Value {
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl EndpointsMut for serde_json::Value { impl EndpointsMut for serde_json::Value {
crate::setter! { proxy_url::proxyUrl -> &str } crate::setter! { proxyUrl -> &str }
crate::setter! { oauth_authorization_endpoint::oauthAuthorizationEndpoint -> &str } crate::setter! { oauthAuthorizationEndpoint -> &str }
crate::setter! { oauth_token_endpoint::oauthTokenEndpoint -> &str } crate::setter! { oauthTokenEndpoint -> &str }
crate::setter! { provide_client_key::provideClientKey -> &str } crate::setter! { provideClientKey -> &str }
crate::setter! { sign_client_key::signClientKey -> &str } crate::setter! { signClientKey -> &str }
crate::setter! { shared_inbox::sharedInbox -> &str } crate::setter! { sharedInbox -> &str }
} }

View file

@ -1,7 +1,7 @@
pub mod page; pub mod page;
pub use page::CollectionPage; pub use page::CollectionPage;
use crate::{Node, Object, ObjectMut}; use crate::{Field, FieldErr, Node, Object, ObjectMut};
crate::strenum! { crate::strenum! {
pub enum CollectionType { pub enum CollectionType {
@ -15,9 +15,9 @@ crate::strenum! {
pub trait Collection : Object { pub trait Collection : Object {
type CollectionPage : CollectionPage; type CollectionPage : CollectionPage;
fn collection_type(&self) -> Option<CollectionType> { None } fn collection_type(&self) -> Field<CollectionType> { Err(FieldErr("type")) }
fn total_items(&self) -> Option<u64> { None } fn total_items(&self) -> Field<u64> { Err(FieldErr("totalItems")) }
fn current(&self) -> Node<Self::CollectionPage> { Node::Empty } fn current(&self) -> Node<Self::CollectionPage> { Node::Empty }
fn first(&self) -> Node<Self::CollectionPage> { Node::Empty } fn first(&self) -> Node<Self::CollectionPage> { Node::Empty }
fn last(&self) -> Node<Self::CollectionPage> { Node::Empty } fn last(&self) -> Node<Self::CollectionPage> { Node::Empty }
@ -42,12 +42,12 @@ impl Collection for serde_json::Value {
type CollectionPage = serde_json::Value; type CollectionPage = serde_json::Value;
crate::getter! { collection_type -> type CollectionType } crate::getter! { collection_type -> type CollectionType }
crate::getter! { total_items::totalItems -> u64 } crate::getter! { totalItems -> u64 }
crate::getter! { current -> node Self::CollectionPage } crate::getter! { current -> node Self::CollectionPage }
crate::getter! { first -> node Self::CollectionPage } crate::getter! { first -> node Self::CollectionPage }
crate::getter! { last -> node Self::CollectionPage } crate::getter! { last -> node Self::CollectionPage }
crate::getter! { items -> node <Self as Object>::Object } crate::getter! { items -> node <Self as Object>::Object }
crate::getter! { ordered_items::orderedItems -> node <Self as Object>::Object } crate::getter! { orderedItems -> node <Self as Object>::Object }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
@ -55,10 +55,10 @@ impl CollectionMut for serde_json::Value {
type CollectionPage = serde_json::Value; type CollectionPage = serde_json::Value;
crate::setter! { collection_type -> type CollectionType } crate::setter! { collection_type -> type CollectionType }
crate::setter! { total_items::totalItems -> u64 } crate::setter! { totalItems -> u64 }
crate::setter! { current -> node Self::CollectionPage } crate::setter! { current -> node Self::CollectionPage }
crate::setter! { first -> node Self::CollectionPage } crate::setter! { first -> node Self::CollectionPage }
crate::setter! { last -> node Self::CollectionPage } crate::setter! { last -> node Self::CollectionPage }
crate::setter! { items -> node <Self as Object>::Object } crate::setter! { items -> node <Self as Object>::Object }
crate::setter! { ordered_items::orderedItems -> node <Self as Object>::Object } crate::setter! { orderedItems -> node <Self as Object>::Object }
} }

View file

@ -14,14 +14,14 @@ pub trait CollectionPageMut : super::CollectionMut {
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl CollectionPage for serde_json::Value { impl CollectionPage for serde_json::Value {
crate::getter! { part_of::partOf -> node Self::Collection } crate::getter! { partOf -> node Self::Collection }
crate::getter! { next -> node Self::CollectionPage } crate::getter! { next -> node Self::CollectionPage }
crate::getter! { prev -> node Self::CollectionPage } crate::getter! { prev -> node Self::CollectionPage }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl CollectionPageMut for serde_json::Value { impl CollectionPageMut for serde_json::Value {
crate::setter! { part_of::partOf -> node Self::Collection } crate::setter! { partOf -> node Self::Collection }
crate::setter! { next -> node Self::CollectionPage } crate::setter! { next -> node Self::CollectionPage }
crate::setter! { prev -> node Self::CollectionPage } crate::setter! { prev -> node Self::CollectionPage }
} }

View file

@ -9,7 +9,7 @@ crate::strenum! {
} }
pub trait Document : super::Object { pub trait Document : super::Object {
fn document_type(&self) -> Option<DocumentType> { None } fn document_type(&self) -> crate::Field<DocumentType> { Err(crate::FieldErr("type")) }
} }
pub trait DocumentMut : super::ObjectMut { pub trait DocumentMut : super::ObjectMut {
@ -19,10 +19,10 @@ pub trait DocumentMut : super::ObjectMut {
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl Document for serde_json::Value { impl Document for serde_json::Value {
crate::getter! { document_type -> type DocumentType } crate::getter! { documentType -> type DocumentType }
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl DocumentMut for serde_json::Value { impl DocumentMut for serde_json::Value {
crate::setter! { document_type -> type DocumentType } crate::setter! { documentType -> type DocumentType }
} }

View file

@ -7,7 +7,7 @@ pub mod place;
pub mod profile; pub mod profile;
pub mod relationship; pub mod relationship;
use crate::{Base, BaseMut, Node}; use crate::{Base, BaseMut, Field, FieldErr, Node};
use actor::ActorType; use actor::ActorType;
use document::DocumentType; use document::DocumentType;
@ -40,51 +40,51 @@ pub trait Object : Base {
type Document : crate::Document; type Document : crate::Document;
type Activity : crate::Activity; type Activity : crate::Activity;
fn object_type(&self) -> Option<ObjectType> { None } fn object_type(&self) -> Field<ObjectType> { Err(FieldErr("type")) }
fn attachment(&self) -> Node<Self::Object> { Node::Empty } fn attachment(&self) -> Node<Self::Object> { Node::Empty }
fn attributed_to(&self) -> Node<Self::Actor> { Node::Empty } fn attributed_to(&self) -> Node<Self::Actor> { Node::Empty }
fn audience(&self) -> Node<Self::Actor> { Node::Empty } fn audience(&self) -> Node<Self::Actor> { Node::Empty }
fn content(&self) -> Option<&str> { None } // TODO handle language maps fn content(&self) -> Field<&str> { Err(FieldErr("content")) } // TODO handle language maps
fn context(&self) -> Node<Self::Object> { Node::Empty } fn context(&self) -> Node<Self::Object> { Node::Empty }
fn name(&self) -> Option<&str> { None } // also in link // TODO handle language maps fn name(&self) -> Field<&str> { Err(FieldErr("name")) } // also in link // TODO handle language maps
fn end_time(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn end_time(&self) -> Field<chrono::DateTime<chrono::Utc>> { Err(FieldErr("endTime")) }
fn generator(&self) -> Node<Self::Actor> { Node::Empty } fn generator(&self) -> Node<Self::Actor> { Node::Empty }
fn icon(&self) -> Node<Self::Document> { Node::Empty } fn icon(&self) -> Node<Self::Document> { Node::Empty }
fn image(&self) -> Node<Self::Document> { Node::Empty } fn image(&self) -> Node<Self::Document> { Node::Empty }
fn in_reply_to(&self) -> Node<Self::Object> { Node::Empty } fn in_reply_to(&self) -> Node<Self::Object> { Node::Empty }
fn location(&self) -> Node<Self::Object> { Node::Empty } fn location(&self) -> Node<Self::Object> { Node::Empty }
fn preview(&self) -> Node<Self::Object> { Node::Empty } // also in link fn preview(&self) -> Node<Self::Object> { Node::Empty } // also in link
fn published(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn published(&self) -> Field<chrono::DateTime<chrono::Utc>> { Err(FieldErr("published")) }
fn updated(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn updated(&self) -> Field<chrono::DateTime<chrono::Utc>> { Err(FieldErr("updated")) }
fn replies(&self) -> Node<Self::Collection> { Node::Empty } fn replies(&self) -> Node<Self::Collection> { Node::Empty }
fn likes(&self) -> Node<Self::Collection> { Node::Empty } fn likes(&self) -> Node<Self::Collection> { Node::Empty }
fn shares(&self) -> Node<Self::Collection> { Node::Empty } fn shares(&self) -> Node<Self::Collection> { Node::Empty }
fn start_time(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn start_time(&self) -> Field<chrono::DateTime<chrono::Utc>> { Err(FieldErr("startTime")) }
fn summary(&self) -> Option<&str> { None } fn summary(&self) -> Field<&str> { Err(FieldErr("summary")) }
fn tag(&self) -> Node<Self::Object> { Node::Empty } fn tag(&self) -> Node<Self::Object> { Node::Empty }
fn url(&self) -> Node<Self::Link> { Node::Empty } fn url(&self) -> Node<Self::Link> { Node::Empty }
fn to(&self) -> Node<Self::Link> { Node::Empty } fn to(&self) -> Node<Self::Link> { Node::Empty }
fn bto(&self) -> Node<Self::Link> { Node::Empty } fn bto(&self) -> Node<Self::Link> { Node::Empty }
fn cc(&self) -> Node<Self::Link> { Node::Empty } fn cc(&self) -> Node<Self::Link> { Node::Empty }
fn bcc(&self) -> Node<Self::Link> { Node::Empty } fn bcc(&self) -> Node<Self::Link> { Node::Empty }
fn media_type(&self) -> Option<&str> { None } // also in link fn media_type(&self) -> Field<&str> { Err(FieldErr("mediaType")) } // also in link
fn duration(&self) -> Option<&str> { None } // TODO how to parse xsd:duration ? fn duration(&self) -> Field<&str> { Err(FieldErr("duration")) } // TODO how to parse xsd:duration ?
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
fn sensitive(&self) -> Option<bool> { None } fn sensitive(&self) -> Field<bool> { Err(FieldErr("sensitive")) }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
fn quote_url(&self) -> Node<Self::Object> { Node::Empty } fn quote_url(&self) -> Node<Self::Object> { Node::Empty }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
fn liked_by_me(&self) -> Option<bool> { None } fn liked_by_me(&self) -> Field<bool> { Err(FieldErr("likedByMe")) }
#[cfg(feature = "ostatus")] #[cfg(feature = "ostatus")]
fn conversation(&self) -> Node<Self::Object> { Node::Empty } fn conversation(&self) -> Node<Self::Object> { Node::Empty }
fn as_activity(&self) -> Option<&Self::Activity> { None } fn as_activity(&self) -> Result<&Self::Activity, FieldErr> { Err(FieldErr("type")) }
fn as_actor(&self) -> Option<&Self::Actor> { None } fn as_actor(&self) -> Result<&Self::Actor, FieldErr> { Err(FieldErr("type")) }
fn as_collection(&self) -> Option<&Self::Collection> { None } fn as_collection(&self) -> Result<&Self::Collection, FieldErr> { Err(FieldErr("type")) }
fn as_document(&self) -> Option<&Self::Document> { None } fn as_document(&self) -> Result<&Self::Document, FieldErr> { Err(FieldErr("type")) }
} }
pub trait ObjectMut : BaseMut { pub trait ObjectMut : BaseMut {
@ -145,18 +145,18 @@ impl Object for serde_json::Value {
type Collection = serde_json::Value; type Collection = serde_json::Value;
type Activity = serde_json::Value; type Activity = serde_json::Value;
crate::getter! { object_type -> type ObjectType } crate::getter! { objectType -> type ObjectType }
crate::getter! { attachment -> node <Self as Object>::Object } crate::getter! { attachment -> node <Self as Object>::Object }
crate::getter! { attributed_to::attributedTo -> node Self::Actor } crate::getter! { attributedTo -> node Self::Actor }
crate::getter! { audience -> node Self::Actor } crate::getter! { audience -> node Self::Actor }
crate::getter! { content -> &str } crate::getter! { content -> &str }
crate::getter! { context -> node <Self as Object>::Object } crate::getter! { context -> node <Self as Object>::Object }
crate::getter! { name -> &str } crate::getter! { name -> &str }
crate::getter! { end_time::endTime -> chrono::DateTime<chrono::Utc> } crate::getter! { endTime -> chrono::DateTime<chrono::Utc> }
crate::getter! { generator -> node Self::Actor } crate::getter! { generator -> node Self::Actor }
crate::getter! { icon -> node Self::Document } crate::getter! { icon -> node Self::Document }
crate::getter! { image -> node Self::Document } crate::getter! { image -> node Self::Document }
crate::getter! { in_reply_to::inReplyTo -> node <Self as Object>::Object } crate::getter! { inReplyTo -> node <Self as Object>::Object }
crate::getter! { location -> node <Self as Object>::Object } crate::getter! { location -> node <Self as Object>::Object }
crate::getter! { preview -> node <Self as Object>::Object } crate::getter! { preview -> node <Self as Object>::Object }
crate::getter! { published -> chrono::DateTime<chrono::Utc> } crate::getter! { published -> chrono::DateTime<chrono::Utc> }
@ -164,53 +164,53 @@ impl Object for serde_json::Value {
crate::getter! { replies -> node Self::Collection } crate::getter! { replies -> node Self::Collection }
crate::getter! { likes -> node Self::Collection } crate::getter! { likes -> node Self::Collection }
crate::getter! { shares -> node Self::Collection } crate::getter! { shares -> node Self::Collection }
crate::getter! { start_time::startTime -> chrono::DateTime<chrono::Utc> } crate::getter! { startTime -> chrono::DateTime<chrono::Utc> }
crate::getter! { summary -> &str } crate::getter! { summary -> &str }
crate::getter! { tag -> node <Self as Object>::Object } crate::getter! { tag -> node <Self as Object>::Object }
crate::getter! { to -> node Self::Link } crate::getter! { to -> node Self::Link }
crate::getter! { bto -> node Self::Link } crate::getter! { bto -> node Self::Link }
crate::getter! { cc -> node Self::Link } crate::getter! { cc -> node Self::Link }
crate::getter! { bcc -> node Self::Link } crate::getter! { bcc -> node Self::Link }
crate::getter! { media_type::mediaType -> &str } crate::getter! { mediaType -> &str }
crate::getter! { duration -> &str } crate::getter! { duration -> &str }
crate::getter! { url -> node Self::Link } crate::getter! { url -> node Self::Link }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::getter! { sensitive -> bool } crate::getter! { sensitive -> bool }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::getter! { quote_url::quoteUrl -> node <Self as Object>::Object } crate::getter! { quoteUrl -> node <Self as Object>::Object }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::getter! { liked_by_me::likedByMe -> bool } crate::getter! { likedByMe -> bool }
#[cfg(feature = "ostatus")] #[cfg(feature = "ostatus")]
crate::getter! { conversation -> node <Self as Object>::Object } crate::getter! { conversation -> node <Self as Object>::Object }
fn as_activity(&self) -> Option<&Self::Activity> { fn as_activity(&self) -> Result<&Self::Activity, FieldErr> {
match self.object_type() { match self.object_type()? {
Some(ObjectType::Activity(_)) => Some(self), ObjectType::Activity(_) => Ok(self),
_ => None, _ => Err(FieldErr("type")),
} }
} }
fn as_actor(&self) -> Option<&Self::Actor> { fn as_actor(&self) -> Result<&Self::Actor, FieldErr> {
match self.object_type() { match self.object_type()? {
Some(ObjectType::Actor(_)) => Some(self), ObjectType::Actor(_) => Ok(self),
_ => None, _ => Err(FieldErr("type")),
} }
} }
fn as_collection(&self) -> Option<&Self::Collection> { fn as_collection(&self) -> Result<&Self::Collection, FieldErr> {
match self.object_type() { match self.object_type()? {
Some(ObjectType::Collection(_)) => Some(self), ObjectType::Collection(_) => Ok(self),
_ => None, _ => Err(FieldErr("type")),
} }
} }
fn as_document(&self) -> Option<&Self::Document> { fn as_document(&self) -> Result<&Self::Document, FieldErr> {
match self.object_type() { match self.object_type()? {
Some(ObjectType::Document(_)) => Some(self), ObjectType::Document(_) => Ok(self),
_ => None, _ => Err(FieldErr("type")),
} }
} }
} }
@ -225,16 +225,16 @@ impl ObjectMut for serde_json::Value {
crate::setter! { object_type -> type ObjectType } crate::setter! { object_type -> type ObjectType }
crate::setter! { attachment -> node <Self as Object>::Object } crate::setter! { attachment -> node <Self as Object>::Object }
crate::setter! { attributed_to::attributedTo -> node Self::Actor } crate::setter! { attributedTo -> node Self::Actor }
crate::setter! { audience -> node Self::Actor } crate::setter! { audience -> node Self::Actor }
crate::setter! { content -> &str } crate::setter! { content -> &str }
crate::setter! { context -> node <Self as Object>::Object } crate::setter! { context -> node <Self as Object>::Object }
crate::setter! { name -> &str } crate::setter! { name -> &str }
crate::setter! { end_time::endTime -> chrono::DateTime<chrono::Utc> } crate::setter! { endTime -> chrono::DateTime<chrono::Utc> }
crate::setter! { generator -> node Self::Actor } crate::setter! { generator -> node Self::Actor }
crate::setter! { icon -> node Self::Document } crate::setter! { icon -> node Self::Document }
crate::setter! { image -> node Self::Document } crate::setter! { image -> node Self::Document }
crate::setter! { in_reply_to::inReplyTo -> node <Self as Object>::Object } crate::setter! { inReplyTo -> node <Self as Object>::Object }
crate::setter! { location -> node <Self as Object>::Object } crate::setter! { location -> node <Self as Object>::Object }
crate::setter! { preview -> node <Self as Object>::Object } crate::setter! { preview -> node <Self as Object>::Object }
crate::setter! { published -> chrono::DateTime<chrono::Utc> } crate::setter! { published -> chrono::DateTime<chrono::Utc> }
@ -242,24 +242,24 @@ impl ObjectMut for serde_json::Value {
crate::setter! { replies -> node Self::Collection } crate::setter! { replies -> node Self::Collection }
crate::setter! { likes -> node Self::Collection } crate::setter! { likes -> node Self::Collection }
crate::setter! { shares -> node Self::Collection } crate::setter! { shares -> node Self::Collection }
crate::setter! { start_time::startTime -> chrono::DateTime<chrono::Utc> } crate::setter! { startTime -> chrono::DateTime<chrono::Utc> }
crate::setter! { summary -> &str } crate::setter! { summary -> &str }
crate::setter! { tag -> node <Self as Object>::Object } crate::setter! { tag -> node <Self as Object>::Object }
crate::setter! { to -> node Self::Link } crate::setter! { to -> node Self::Link }
crate::setter! { bto -> node Self::Link} crate::setter! { bto -> node Self::Link}
crate::setter! { cc -> node Self::Link } crate::setter! { cc -> node Self::Link }
crate::setter! { bcc -> node Self::Link } crate::setter! { bcc -> node Self::Link }
crate::setter! { media_type::mediaType -> &str } crate::setter! { mediaType -> &str }
crate::setter! { duration -> &str } crate::setter! { duration -> &str }
crate::setter! { url -> node Self::Link } crate::setter! { url -> node Self::Link }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::setter! { sensitive -> bool } crate::setter! { sensitive -> bool }
#[cfg(feature = "activitypub-miscellaneous-terms")] #[cfg(feature = "activitypub-miscellaneous-terms")]
crate::setter! { quote_url::quoteUrl -> node <Self as Object>::Object } crate::setter! { quoteUrl -> node <Self as Object>::Object }
#[cfg(feature = "activitypub-fe")] #[cfg(feature = "activitypub-fe")]
crate::setter! { liked_by_me::likedByMe -> bool } crate::setter! { likedByMe -> bool }
#[cfg(feature = "ostatus")] #[cfg(feature = "ostatus")]
crate::setter! { conversation -> node <Self as Object>::Object } crate::setter! { conversation -> node <Self as Object>::Object }

View file

@ -1,10 +1,12 @@
use crate::{Field, FieldErr};
pub trait Place : super::Object { pub trait Place : super::Object {
fn accuracy(&self) -> Option<f64> { None } fn accuracy(&self) -> Field<f64> { Err(FieldErr("accuracy")) }
fn altitude(&self) -> Option<f64> { None } fn altitude(&self) -> Field<f64> { Err(FieldErr("altitude")) }
fn latitude(&self) -> Option<f64> { None } fn latitude(&self) -> Field<f64> { Err(FieldErr("latitude")) }
fn longitude(&self) -> Option<f64> { None } fn longitude(&self) -> Field<f64> { Err(FieldErr("longitude")) }
fn radius(&self) -> Option<f64> { None } fn radius(&self) -> Field<f64> { Err(FieldErr("radius")) }
fn units(&self) -> Option<&str> { None } fn units(&self) -> Field<&str> { Err(FieldErr("units")) }
} }
pub trait PlaceMut : super::ObjectMut { pub trait PlaceMut : super::ObjectMut {

View file

@ -1,6 +1,6 @@
pub trait Tombstone : super::Object { pub trait Tombstone : super::Object {
fn former_type(&self) -> Option<crate::BaseType> { None } fn former_type(&self) -> crate::Field<crate::BaseType> { Err(crate::FieldErr("formerType")) }
fn deleted(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn deleted(&self) -> crate::Field<chrono::DateTime<chrono::Utc>> { Err(crate::FieldErr("deleted")) }
} }
pub trait TombstoneMut : super::ObjectMut { pub trait TombstoneMut : super::ObjectMut {