From 40e01fe83bb778446a10d2f258c51e57f20e540c Mon Sep 17 00:00:00 2001 From: alemi Date: Sat, 1 Jun 2024 01:04:03 +0200 Subject: [PATCH] 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() --- apb/Cargo.toml | 2 +- apb/src/key.rs | 2 +- apb/src/lib.rs | 7 +- apb/src/macros.rs | 227 +++++++----------- apb/src/node.rs | 2 +- apb/src/server.rs | 33 --- apb/src/target.rs | 30 ++- apb/src/types/base.rs | 29 ++- apb/src/types/link.rs | 34 +-- apb/src/types/object/activity/accept.rs | 2 +- apb/src/types/object/activity/ignore.rs | 2 +- apb/src/types/object/activity/intransitive.rs | 2 +- apb/src/types/object/activity/mod.rs | 4 +- apb/src/types/object/activity/offer.rs | 2 +- apb/src/types/object/activity/reject.rs | 2 +- apb/src/types/object/actor.rs | 94 ++++---- apb/src/types/object/collection/mod.rs | 14 +- apb/src/types/object/collection/page.rs | 4 +- apb/src/types/object/document.rs | 6 +- apb/src/types/object/mod.rs | 96 ++++---- apb/src/types/object/place.rs | 14 +- apb/src/types/object/tombstone.rs | 4 +- 22 files changed, 290 insertions(+), 322 deletions(-) delete mode 100644 apb/src/server.rs diff --git a/apb/Cargo.toml b/apb/Cargo.toml index 8486c178..0276874e 100644 --- a/apb/Cargo.toml +++ b/apb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apb" -version = "0.1.1" +version = "0.2.0" edition = "2021" authors = [ "alemi " ] description = "Traits and types to handle ActivityPub objects" diff --git a/apb/src/key.rs b/apb/src/key.rs index 8a7f6e27..fe41f8b7 100644 --- a/apb/src/key.rs +++ b/apb/src/key.rs @@ -1,7 +1,7 @@ // TODO technically this is not part of ActivityStreams 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; } diff --git a/apb/src/lib.rs b/apb/src/lib.rs index 00afef1b..bf0feb4e 100644 --- a/apb/src/lib.rs +++ b/apb/src/lib.rs @@ -93,7 +93,6 @@ pub(crate) use macros::{strenum, getter, setter}; mod node; pub use node::Node; -pub mod server; pub mod target; 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 = Result; + #[cfg(feature = "unstructured")] pub fn new() -> serde_json::Value { serde_json::Value::Object(serde_json::Map::default()) diff --git a/apb/src/macros.rs b/apb/src/macros.rs index 2d05f3e2..dd062aae 100644 --- a/apb/src/macros.rs +++ b/apb/src/macros.rs @@ -110,101 +110,93 @@ pub(crate) use strenum; macro_rules! getter { ($name:ident -> type $t:ty) => { - fn $name(&self) -> Option<$t> { - self.get("type")?.as_str()?.try_into().ok() - } - }; - - ($name:ident -> bool) => { - fn $name(&self) -> Option { - 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 { - 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 { - self.get(stringify!($name))?.as_f64() - } - }; - - ($name:ident::$rename:ident -> f64) => { - fn $name(&self) -> Option { - self.get(stringify!($rename))?.as_f64() - } - }; - - ($name:ident -> u64) => { - fn $name(&self) -> Option { - self.get(stringify!($name))?.as_u64() - } - }; - - ($name:ident::$rename:ident -> u64) => { - fn $name(&self) -> Option { - self.get(stringify!($rename))?.as_u64() - } - }; - - ($name:ident -> chrono::DateTime) => { - fn $name(&self) -> Option> { - Some( - chrono::DateTime::parse_from_rfc3339( - self - .get(stringify!($name))? - .as_str()? - ) - .ok()? - .with_timezone(&chrono::Utc) - ) - } - }; - - ($name:ident::$rename:ident -> chrono::DateTime) => { - fn $name(&self) -> Option> { - 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, + paste::paste! { + fn [< $name:snake >] (&self) -> $crate::Field<$t> { + self.get("type") + .and_then(|x| x.as_str()) + .and_then(|x| x.try_into().ok()) + .ok_or($crate::FieldErr("type")) } } }; - ($name:ident::$rename:ident -> node $t:ty) => { - fn $name(&self) -> $crate::Node<$t> { - match self.get(stringify!($rename)) { - Some(x) => $crate::Node::from(x.clone()), - None => $crate::Node::Empty, + ($name:ident -> bool) => { + paste::paste! { + fn [< $name:snake >](&self) -> $crate::Field { + self.get(stringify!($name)) + .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 { + 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 { + 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 { + self.get(stringify!($name)) + .and_then(|x| x.as_i64()) + .ok_or($crate::FieldErr(stringify!($name))) + } + } + }; + + ($name:ident -> chrono::DateTime) => { + paste::paste! { + fn [< $name:snake >](&self) -> $crate::Field> { + 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 { ($name:ident -> bool) => { paste::item! { - fn [< set_$name >](mut self, val: Option) -> Self { + fn [< set_$name:snake >](mut self, val: Option) -> Self { $crate::macros::set_maybe_value( &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) -> Self { - $crate::macros::set_maybe_value( - &mut self, stringify!($rename), val.map(|x| serde_json::Value::Bool(x)) - ); - self - } - } - }; - ($name:ident -> &str) => { 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( &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) => { paste::item! { - fn [< set_$name >](mut self, val: Option) -> Self { + fn [< set_$name:snake >](mut self, val: Option) -> Self { $crate::macros::set_maybe_value( &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! { - fn [< set_$name >](mut self, val: Option) -> Self { + fn [< set_$name:snake >](mut self, val: Option) -> Self { $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 } @@ -281,7 +251,7 @@ macro_rules! setter { ($name:ident -> chrono::DateTime) => { paste::item! { - fn [< set_$name >](mut self, val: Option>) -> Self { + fn [< set_$name:snake >](mut self, val: Option>) -> Self { $crate::macros::set_maybe_value( &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) => { - paste::item! { - fn [< set_$name >](mut self, val: Option>) -> 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 ) => { 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( &mut self, stringify!($name), val ); @@ -314,7 +273,7 @@ macro_rules! setter { ($name:ident::$rename:ident -> node $t:ty ) => { 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( &mut self, stringify!($rename), val ); @@ -325,7 +284,7 @@ macro_rules! setter { ($name:ident -> type $t:ty ) => { 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( &mut self, "type", val.map(|x| serde_json::Value::String(x.as_ref().to_string())) ); diff --git a/apb/src/node.rs b/apb/src/node.rs index a1312e45..506b7492 100644 --- a/apb/src/node.rs +++ b/apb/src/node.rs @@ -104,7 +104,7 @@ impl Node { match self { Node::Empty => None, 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()), } } diff --git a/apb/src/server.rs b/apb/src/server.rs deleted file mode 100644 index e76a53a3..00000000 --- a/apb/src/server.rs +++ /dev/null @@ -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; - async fn create(&self, uid: String, activity: Self::Activity) -> Result; - async fn like(&self, uid: String, activity: Self::Activity) -> Result; - async fn follow(&self, uid: String, activity: Self::Activity) -> Result; - async fn announce(&self, uid: String, activity: Self::Activity) -> Result; - async fn accept(&self, uid: String, activity: Self::Activity) -> Result; - async fn reject(&self, _uid: String, _activity: Self::Activity) -> Result; - async fn undo(&self, uid: String, activity: Self::Activity) -> Result; - async fn delete(&self, uid: String, activity: Self::Activity) -> Result; - async fn update(&self, uid: String, activity: Self::Activity) -> Result; -} - -#[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>; -} diff --git a/apb/src/target.rs b/apb/src/target.rs index 79a8a412..f4096f59 100644 --- a/apb/src/target.rs +++ b/apb/src/target.rs @@ -3,7 +3,11 @@ use crate::Object; pub const PUBLIC : &str = "https://www.w3.org/ns/activitystreams#Public"; pub trait Addressed { - fn addressed(&self) -> Vec; + fn addressed(&self) -> Vec; // TODO rename this? remate others? idk + fn primary_targets(&self) -> Vec; + fn secondary_targets(&self) -> Vec; + fn public_targets(&self) -> Vec; + fn private_targets(&self) -> Vec; } impl Addressed for T { @@ -14,4 +18,28 @@ impl Addressed for T { to.append(&mut self.bcc().ids()); to } + + fn primary_targets(&self) -> Vec { + let mut to : Vec = self.to().ids(); + to.append(&mut self.bto().ids()); + to + } + + fn secondary_targets(&self) -> Vec { + let mut to : Vec = self.cc().ids(); + to.append(&mut self.bcc().ids()); + to + } + + fn public_targets(&self) -> Vec { + let mut to : Vec = self.to().ids(); + to.append(&mut self.cc().ids()); + to + } + + fn private_targets(&self) -> Vec { + let mut to : Vec = self.bto().ids(); + to.append(&mut self.bcc().ids()); + to + } } diff --git a/apb/src/types/base.rs b/apb/src/types/base.rs index e992435c..44b271ec 100644 --- a/apb/src/types/base.rs +++ b/apb/src/types/base.rs @@ -9,8 +9,8 @@ crate::strenum! { } pub trait Base : crate::macros::MaybeSend { - fn id(&self) -> Option<&str> { None } - fn base_type(&self) -> Option { None } + fn id(&self) -> crate::Field<&str> { Err(crate::FieldErr("id")) } + fn base_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } @@ -21,30 +21,35 @@ pub trait BaseMut : crate::macros::MaybeSend { impl Base for String { - fn id(&self) -> Option<&str> { - Some(self) + fn id(&self) -> crate::Field<&str> { + Ok(self) } - fn base_type(&self) -> Option { - Some(BaseType::Link(LinkType::Link)) + fn base_type(&self) -> crate::Field { + Ok(BaseType::Link(LinkType::Link)) } } #[cfg(feature = "unstructured")] impl Base for serde_json::Value { - fn base_type(&self) -> Option { + fn base_type(&self) -> crate::Field { if self.is_string() { - Some(BaseType::Link(LinkType::Link)) + Ok(BaseType::Link(LinkType::Link)) } 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() { - self.as_str() + Ok(self.as_str().ok_or(crate::FieldErr("id"))?) } else { - self.get("id").map(|x| x.as_str())? + self.get("id") + .and_then(|x| x.as_str()) + .ok_or(crate::FieldErr("id")) } } } diff --git a/apb/src/types/link.rs b/apb/src/types/link.rs index 774be396..ec8a4276 100644 --- a/apb/src/types/link.rs +++ b/apb/src/types/link.rs @@ -1,3 +1,5 @@ +use crate::{Field, FieldErr}; + #[cfg(feature = "activitypub-miscellaneous-terms")] crate::strenum! { pub enum LinkType { @@ -17,24 +19,24 @@ crate::strenum! { pub trait Link : crate::Base { fn href(&self) -> &str; - fn rel(&self) -> Option<&str> { None } - fn link_media_type(&self) -> Option<&str> { None } // also in obj - fn link_name(&self) -> Option<&str> { None } // also in obj - fn hreflang(&self) -> Option<&str> { None } - fn height(&self) -> Option { None } - fn width(&self) -> Option { None } - fn link_preview(&self) -> Option<&str> { None } // also in obj + fn rel(&self) -> Field<&str> { Err(FieldErr("rel")) } + fn media_type(&self) -> Field<&str> { Err(FieldErr("mediaType")) } // also in obj + fn name(&self) -> Field<&str> { Err(FieldErr("name")) } // also in obj + fn hreflang(&self) -> Field<&str> { Err(FieldErr("hreflang")) } + fn height(&self) -> Field { Err(FieldErr("height")) } + fn width(&self) -> Field { Err(FieldErr("width")) } + fn preview(&self) -> Field<&str> { Err(FieldErr("linkPreview")) } // also in obj } pub trait LinkMut : crate::BaseMut { fn set_href(self, href: &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_link_name(self, val: Option<&str>) -> Self; // also in obj + fn set_media_type(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_height(self, val: Option) -> Self; fn set_width(self, val: Option) -> 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 { @@ -55,12 +57,12 @@ impl Link for serde_json::Value { } crate::getter! { rel -> &str } - crate::getter! { link_media_type::mediaType -> &str } - crate::getter! { link_name::name -> &str } + crate::getter! { mediaType -> &str } + crate::getter! { name -> &str } crate::getter! { hreflang -> &str } crate::getter! { height -> u64 } crate::getter! { width -> u64 } - crate::getter! { link_preview::preview -> &str } + crate::getter! { preview -> &str } } #[cfg(feature = "unstructured")] @@ -79,10 +81,10 @@ impl LinkMut for serde_json::Value { } crate::setter! { rel -> &str } - crate::setter! { link_media_type::mediaType -> &str } - crate::setter! { link_name::name -> &str } + crate::setter! { mediaType -> &str } + crate::setter! { name -> &str } crate::setter! { hreflang -> &str } crate::setter! { height -> u64 } crate::setter! { width -> u64 } - crate::setter! { link_preview::preview -> &str } + crate::setter! { preview -> &str } } diff --git a/apb/src/types/object/activity/accept.rs b/apb/src/types/object/activity/accept.rs index 93c35aa3..45a42fba 100644 --- a/apb/src/types/object/activity/accept.rs +++ b/apb/src/types/object/activity/accept.rs @@ -8,7 +8,7 @@ strenum! { } pub trait Accept : super::Activity { - fn accept_type(&self) -> Option { None } + fn accept_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait AcceptMut : super::ActivityMut { diff --git a/apb/src/types/object/activity/ignore.rs b/apb/src/types/object/activity/ignore.rs index f3688bbc..8162e5bd 100644 --- a/apb/src/types/object/activity/ignore.rs +++ b/apb/src/types/object/activity/ignore.rs @@ -8,7 +8,7 @@ strenum! { } pub trait Ignore : super::Activity { - fn ignore_type(&self) -> Option { None } + fn ignore_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait IgnoreMut : super::ActivityMut { diff --git a/apb/src/types/object/activity/intransitive.rs b/apb/src/types/object/activity/intransitive.rs index d742cbf4..c7e792f8 100644 --- a/apb/src/types/object/activity/intransitive.rs +++ b/apb/src/types/object/activity/intransitive.rs @@ -10,7 +10,7 @@ strenum! { } pub trait IntransitiveActivity : super::Activity { - fn intransitive_activity_type(&self) -> Option { None } + fn intransitive_activity_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait IntransitiveActivityMut : super::ActivityMut { diff --git a/apb/src/types/object/activity/mod.rs b/apb/src/types/object/activity/mod.rs index 90c12eb4..81b95062 100644 --- a/apb/src/types/object/activity/mod.rs +++ b/apb/src/types/object/activity/mod.rs @@ -4,7 +4,7 @@ pub mod intransitive; pub mod offer; pub mod reject; -use crate::{Node, Object, ObjectMut}; +use crate::{Field, FieldErr, Node, Object, ObjectMut}; use accept::AcceptType; use reject::RejectType; use offer::OfferType; @@ -73,7 +73,7 @@ crate::strenum! { } pub trait Activity : Object { - fn activity_type(&self) -> Option { None } + fn activity_type(&self) -> Field { Err(FieldErr("type")) } fn actor(&self) -> Node { Node::Empty } fn object(&self) -> Node { Node::Empty } fn target(&self) -> Node { Node::Empty } diff --git a/apb/src/types/object/activity/offer.rs b/apb/src/types/object/activity/offer.rs index 92cf8b63..a84b25f7 100644 --- a/apb/src/types/object/activity/offer.rs +++ b/apb/src/types/object/activity/offer.rs @@ -8,7 +8,7 @@ strenum! { } pub trait Offer : super::Activity { - fn offer_type(&self) -> Option { None } + fn offer_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait OfferMut : super::ActivityMut { diff --git a/apb/src/types/object/activity/reject.rs b/apb/src/types/object/activity/reject.rs index ed18ffa5..a295a9a1 100644 --- a/apb/src/types/object/activity/reject.rs +++ b/apb/src/types/object/activity/reject.rs @@ -8,7 +8,7 @@ strenum! { } pub trait Reject : super::Activity { - fn reject_type(&self) -> Option { None } + fn reject_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait RejectMut : super::ActivityMut { diff --git a/apb/src/types/object/actor.rs b/apb/src/types/object/actor.rs index 9bd87576..98788a4e 100644 --- a/apb/src/types/object/actor.rs +++ b/apb/src/types/object/actor.rs @@ -1,4 +1,4 @@ -use crate::{Node, Object, ObjectMut}; +use crate::{Field, FieldErr, Node, Object, ObjectMut}; crate::strenum! { pub enum ActorType { @@ -14,8 +14,8 @@ pub trait Actor : Object { type PublicKey : crate::PublicKey; type Endpoints : Endpoints; - fn actor_type(&self) -> Option { None } - fn preferred_username(&self) -> Option<&str> { None } + fn actor_type(&self) -> Field { Err(FieldErr("type")) } + fn preferred_username(&self) -> Field<&str> { Err(FieldErr("preferredUsername")) } fn inbox(&self) -> Node; fn outbox(&self) -> Node; fn following(&self) -> Node { Node::Empty } @@ -28,37 +28,37 @@ pub trait Actor : Object { #[cfg(feature = "activitypub-miscellaneous-terms")] fn moved_to(&self) -> Node { Node::Empty } #[cfg(feature = "activitypub-miscellaneous-terms")] - fn manually_approves_followers(&self) -> Option { None } + fn manually_approves_followers(&self) -> Field { Err(FieldErr("manuallyApprovesFollowers")) } #[cfg(feature = "activitypub-fe")] - fn following_me(&self) -> Option { None } + fn following_me(&self) -> Field { Err(FieldErr("followingMe")) } #[cfg(feature = "activitypub-fe")] - fn followed_by_me(&self) -> Option { None } + fn followed_by_me(&self) -> Field { Err(FieldErr("followedByMe")) } #[cfg(feature = "activitypub-counters")] - fn followers_count(&self) -> Option { None } + fn followers_count(&self) -> Field { Err(FieldErr("followersCount")) } #[cfg(feature = "activitypub-counters")] - fn following_count(&self) -> Option { None } + fn following_count(&self) -> Field { Err(FieldErr("followingCount")) } #[cfg(feature = "activitypub-counters")] - fn statuses_count(&self) -> Option { None } + fn statuses_count(&self) -> Field { Err(FieldErr("statusesCount")) } #[cfg(feature = "toot")] - fn discoverable(&self) -> Option { None } + fn discoverable(&self) -> Field { Err(FieldErr("discoverable")) } } 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. - 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. - 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. - 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. - 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. - 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. - fn shared_inbox(&self) -> Option<&str> { None } + fn shared_inbox(&self) -> Field<&str> { Err(FieldErr("sharedInbox")) } } pub trait ActorMut : ObjectMut { @@ -117,33 +117,33 @@ impl Actor for serde_json::Value { type PublicKey = serde_json::Value; type Endpoints = serde_json::Value; - crate::getter! { actor_type -> type ActorType } - crate::getter! { preferred_username::preferredUsername -> &str } + crate::getter! { actorType -> type ActorType } + crate::getter! { preferredUsername -> &str } crate::getter! { inbox -> node Self::Collection } crate::getter! { outbox -> node Self::Collection } crate::getter! { following -> node Self::Collection } crate::getter! { followers -> node Self::Collection } crate::getter! { liked -> 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 } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::getter! { moved_to::movedTo -> node Self::Actor } + crate::getter! { movedTo -> node Self::Actor } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::getter! { manually_approves_followers::manuallyApprovedFollowers -> bool } + crate::getter! { manuallyApprovesFollowers -> bool } #[cfg(feature = "activitypub-fe")] - crate::getter! { following_me::followingMe -> bool } + crate::getter! { followingMe -> bool } #[cfg(feature = "activitypub-fe")] - crate::getter! { followed_by_me::followedByMe -> bool } + crate::getter! { followedByMe -> bool } #[cfg(feature = "activitypub-counters")] - crate::getter! { following_count::followingCount -> u64 } + crate::getter! { followingCount -> u64 } #[cfg(feature = "activitypub-counters")] - crate::getter! { followers_count::followersCount -> u64 } + crate::getter! { followersCount -> u64 } #[cfg(feature = "activitypub-counters")] - crate::getter! { statuses_count::statusesCount -> u64 } + crate::getter! { statusesCount -> u64 } #[cfg(feature = "toot")] crate::getter! { discoverable -> bool } @@ -151,12 +151,12 @@ impl Actor for serde_json::Value { #[cfg(feature = "unstructured")] impl Endpoints for serde_json::Value { - crate::getter! { proxy_url::proxyUrl -> &str } - crate::getter! { oauth_authorization_endpoint::oauthAuthorizationEndpoint -> &str } - crate::getter! { oauth_token_endpoint::oauthTokenEndpoint -> &str } - crate::getter! { provide_client_key::provideClientKey -> &str } - crate::getter! { sign_client_key::signClientKey -> &str } - crate::getter! { shared_inbox::sharedInbox -> &str } + crate::getter! { proxyUrl -> &str } + crate::getter! { oauthAuthorizationEndpoint -> &str } + crate::getter! { oauthTokenEndpoint -> &str } + crate::getter! { provideClientKey -> &str } + crate::getter! { signClientKey -> &str } + crate::getter! { sharedInbox -> &str } } #[cfg(feature = "unstructured")] @@ -165,32 +165,32 @@ impl ActorMut for serde_json::Value { type Endpoints = serde_json::Value; crate::setter! { actor_type -> type ActorType } - crate::setter! { preferred_username::preferredUsername -> &str } + crate::setter! { preferredUsername -> &str } crate::setter! { inbox -> node Self::Collection } crate::setter! { outbox -> node Self::Collection } crate::setter! { following -> node Self::Collection } crate::setter! { followers -> node Self::Collection } crate::setter! { liked -> 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 } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::setter! { moved_to::movedTo -> node Self::Actor } + crate::setter! { movedTo -> node Self::Actor } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::setter! { manually_approves_followers::manuallyApprovedFollowers -> bool } + crate::setter! { manuallyApprovesFollowers -> bool } #[cfg(feature = "activitypub-fe")] - crate::setter! { following_me::followingMe -> bool } + crate::setter! { followingMe -> bool } #[cfg(feature = "activitypub-fe")] - crate::setter! { followed_by_me::followedByMe -> bool } + crate::setter! { followedByMe -> bool } #[cfg(feature = "activitypub-counters")] - crate::setter! { following_count::followingCount -> u64 } + crate::setter! { followingCount -> u64 } #[cfg(feature = "activitypub-counters")] - crate::setter! { followers_count::followersCount -> u64 } + crate::setter! { followersCount -> u64 } #[cfg(feature = "activitypub-counters")] - crate::setter! { statuses_count::statusesCount -> u64 } + crate::setter! { statusesCount -> u64 } #[cfg(feature = "toot")] crate::setter! { discoverable -> bool } @@ -198,10 +198,10 @@ impl ActorMut for serde_json::Value { #[cfg(feature = "unstructured")] impl EndpointsMut for serde_json::Value { - crate::setter! { proxy_url::proxyUrl -> &str } - crate::setter! { oauth_authorization_endpoint::oauthAuthorizationEndpoint -> &str } - crate::setter! { oauth_token_endpoint::oauthTokenEndpoint -> &str } - crate::setter! { provide_client_key::provideClientKey -> &str } - crate::setter! { sign_client_key::signClientKey -> &str } - crate::setter! { shared_inbox::sharedInbox -> &str } + crate::setter! { proxyUrl -> &str } + crate::setter! { oauthAuthorizationEndpoint -> &str } + crate::setter! { oauthTokenEndpoint -> &str } + crate::setter! { provideClientKey -> &str } + crate::setter! { signClientKey -> &str } + crate::setter! { sharedInbox -> &str } } diff --git a/apb/src/types/object/collection/mod.rs b/apb/src/types/object/collection/mod.rs index 92d961f0..86f9295f 100644 --- a/apb/src/types/object/collection/mod.rs +++ b/apb/src/types/object/collection/mod.rs @@ -1,7 +1,7 @@ pub mod page; pub use page::CollectionPage; -use crate::{Node, Object, ObjectMut}; +use crate::{Field, FieldErr, Node, Object, ObjectMut}; crate::strenum! { pub enum CollectionType { @@ -15,9 +15,9 @@ crate::strenum! { pub trait Collection : Object { type CollectionPage : CollectionPage; - fn collection_type(&self) -> Option { None } + fn collection_type(&self) -> Field { Err(FieldErr("type")) } - fn total_items(&self) -> Option { None } + fn total_items(&self) -> Field { Err(FieldErr("totalItems")) } fn current(&self) -> Node { Node::Empty } fn first(&self) -> Node { Node::Empty } fn last(&self) -> Node { Node::Empty } @@ -42,12 +42,12 @@ impl Collection for serde_json::Value { type CollectionPage = serde_json::Value; crate::getter! { collection_type -> type CollectionType } - crate::getter! { total_items::totalItems -> u64 } + crate::getter! { totalItems -> u64 } crate::getter! { current -> node Self::CollectionPage } crate::getter! { first -> node Self::CollectionPage } crate::getter! { last -> node Self::CollectionPage } crate::getter! { items -> node ::Object } - crate::getter! { ordered_items::orderedItems -> node ::Object } + crate::getter! { orderedItems -> node ::Object } } #[cfg(feature = "unstructured")] @@ -55,10 +55,10 @@ impl CollectionMut for serde_json::Value { type CollectionPage = serde_json::Value; crate::setter! { collection_type -> type CollectionType } - crate::setter! { total_items::totalItems -> u64 } + crate::setter! { totalItems -> u64 } crate::setter! { current -> node Self::CollectionPage } crate::setter! { first -> node Self::CollectionPage } crate::setter! { last -> node Self::CollectionPage } crate::setter! { items -> node ::Object } - crate::setter! { ordered_items::orderedItems -> node ::Object } + crate::setter! { orderedItems -> node ::Object } } diff --git a/apb/src/types/object/collection/page.rs b/apb/src/types/object/collection/page.rs index a7b13617..9df31a54 100644 --- a/apb/src/types/object/collection/page.rs +++ b/apb/src/types/object/collection/page.rs @@ -14,14 +14,14 @@ pub trait CollectionPageMut : super::CollectionMut { #[cfg(feature = "unstructured")] 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! { prev -> node Self::CollectionPage } } #[cfg(feature = "unstructured")] 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! { prev -> node Self::CollectionPage } } diff --git a/apb/src/types/object/document.rs b/apb/src/types/object/document.rs index 85ec2869..95a7f088 100644 --- a/apb/src/types/object/document.rs +++ b/apb/src/types/object/document.rs @@ -9,7 +9,7 @@ crate::strenum! { } pub trait Document : super::Object { - fn document_type(&self) -> Option { None } + fn document_type(&self) -> crate::Field { Err(crate::FieldErr("type")) } } pub trait DocumentMut : super::ObjectMut { @@ -19,10 +19,10 @@ pub trait DocumentMut : super::ObjectMut { #[cfg(feature = "unstructured")] impl Document for serde_json::Value { - crate::getter! { document_type -> type DocumentType } + crate::getter! { documentType -> type DocumentType } } #[cfg(feature = "unstructured")] impl DocumentMut for serde_json::Value { - crate::setter! { document_type -> type DocumentType } + crate::setter! { documentType -> type DocumentType } } diff --git a/apb/src/types/object/mod.rs b/apb/src/types/object/mod.rs index 749f99c4..50ab2ae7 100644 --- a/apb/src/types/object/mod.rs +++ b/apb/src/types/object/mod.rs @@ -7,7 +7,7 @@ pub mod place; pub mod profile; pub mod relationship; -use crate::{Base, BaseMut, Node}; +use crate::{Base, BaseMut, Field, FieldErr, Node}; use actor::ActorType; use document::DocumentType; @@ -40,51 +40,51 @@ pub trait Object : Base { type Document : crate::Document; type Activity : crate::Activity; - fn object_type(&self) -> Option { None } + fn object_type(&self) -> Field { Err(FieldErr("type")) } fn attachment(&self) -> Node { Node::Empty } fn attributed_to(&self) -> Node { Node::Empty } fn audience(&self) -> Node { 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 { Node::Empty } - fn name(&self) -> Option<&str> { None } // also in link // TODO handle language maps - fn end_time(&self) -> Option> { None } + fn name(&self) -> Field<&str> { Err(FieldErr("name")) } // also in link // TODO handle language maps + fn end_time(&self) -> Field> { Err(FieldErr("endTime")) } fn generator(&self) -> Node { Node::Empty } fn icon(&self) -> Node { Node::Empty } fn image(&self) -> Node { Node::Empty } fn in_reply_to(&self) -> Node { Node::Empty } fn location(&self) -> Node { Node::Empty } fn preview(&self) -> Node { Node::Empty } // also in link - fn published(&self) -> Option> { None } - fn updated(&self) -> Option> { None } + fn published(&self) -> Field> { Err(FieldErr("published")) } + fn updated(&self) -> Field> { Err(FieldErr("updated")) } fn replies(&self) -> Node { Node::Empty } fn likes(&self) -> Node { Node::Empty } fn shares(&self) -> Node { Node::Empty } - fn start_time(&self) -> Option> { None } - fn summary(&self) -> Option<&str> { None } + fn start_time(&self) -> Field> { Err(FieldErr("startTime")) } + fn summary(&self) -> Field<&str> { Err(FieldErr("summary")) } fn tag(&self) -> Node { Node::Empty } fn url(&self) -> Node { Node::Empty } fn to(&self) -> Node { Node::Empty } fn bto(&self) -> Node { Node::Empty } fn cc(&self) -> Node { Node::Empty } fn bcc(&self) -> Node { Node::Empty } - fn media_type(&self) -> Option<&str> { None } // also in link - fn duration(&self) -> Option<&str> { None } // TODO how to parse xsd:duration ? + fn media_type(&self) -> Field<&str> { Err(FieldErr("mediaType")) } // also in link + fn duration(&self) -> Field<&str> { Err(FieldErr("duration")) } // TODO how to parse xsd:duration ? #[cfg(feature = "activitypub-miscellaneous-terms")] - fn sensitive(&self) -> Option { None } + fn sensitive(&self) -> Field { Err(FieldErr("sensitive")) } #[cfg(feature = "activitypub-miscellaneous-terms")] fn quote_url(&self) -> Node { Node::Empty } #[cfg(feature = "activitypub-fe")] - fn liked_by_me(&self) -> Option { None } + fn liked_by_me(&self) -> Field { Err(FieldErr("likedByMe")) } #[cfg(feature = "ostatus")] fn conversation(&self) -> Node { Node::Empty } - fn as_activity(&self) -> Option<&Self::Activity> { None } - fn as_actor(&self) -> Option<&Self::Actor> { None } - fn as_collection(&self) -> Option<&Self::Collection> { None } - fn as_document(&self) -> Option<&Self::Document> { None } + fn as_activity(&self) -> Result<&Self::Activity, FieldErr> { Err(FieldErr("type")) } + fn as_actor(&self) -> Result<&Self::Actor, FieldErr> { Err(FieldErr("type")) } + fn as_collection(&self) -> Result<&Self::Collection, FieldErr> { Err(FieldErr("type")) } + fn as_document(&self) -> Result<&Self::Document, FieldErr> { Err(FieldErr("type")) } } pub trait ObjectMut : BaseMut { @@ -145,18 +145,18 @@ impl Object for serde_json::Value { type Collection = serde_json::Value; type Activity = serde_json::Value; - crate::getter! { object_type -> type ObjectType } + crate::getter! { objectType -> type ObjectType } crate::getter! { attachment -> node ::Object } - crate::getter! { attributed_to::attributedTo -> node Self::Actor } + crate::getter! { attributedTo -> node Self::Actor } crate::getter! { audience -> node Self::Actor } crate::getter! { content -> &str } crate::getter! { context -> node ::Object } crate::getter! { name -> &str } - crate::getter! { end_time::endTime -> chrono::DateTime } + crate::getter! { endTime -> chrono::DateTime } crate::getter! { generator -> node Self::Actor } crate::getter! { icon -> node Self::Document } crate::getter! { image -> node Self::Document } - crate::getter! { in_reply_to::inReplyTo -> node ::Object } + crate::getter! { inReplyTo -> node ::Object } crate::getter! { location -> node ::Object } crate::getter! { preview -> node ::Object } crate::getter! { published -> chrono::DateTime } @@ -164,53 +164,53 @@ impl Object for serde_json::Value { crate::getter! { replies -> node Self::Collection } crate::getter! { likes -> node Self::Collection } crate::getter! { shares -> node Self::Collection } - crate::getter! { start_time::startTime -> chrono::DateTime } + crate::getter! { startTime -> chrono::DateTime } crate::getter! { summary -> &str } crate::getter! { tag -> node ::Object } crate::getter! { to -> node Self::Link } crate::getter! { bto -> node Self::Link } crate::getter! { cc -> 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! { url -> node Self::Link } #[cfg(feature = "activitypub-miscellaneous-terms")] crate::getter! { sensitive -> bool } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::getter! { quote_url::quoteUrl -> node ::Object } + crate::getter! { quoteUrl -> node ::Object } #[cfg(feature = "activitypub-fe")] - crate::getter! { liked_by_me::likedByMe -> bool } + crate::getter! { likedByMe -> bool } #[cfg(feature = "ostatus")] crate::getter! { conversation -> node ::Object } - fn as_activity(&self) -> Option<&Self::Activity> { - match self.object_type() { - Some(ObjectType::Activity(_)) => Some(self), - _ => None, + fn as_activity(&self) -> Result<&Self::Activity, FieldErr> { + match self.object_type()? { + ObjectType::Activity(_) => Ok(self), + _ => Err(FieldErr("type")), } } - fn as_actor(&self) -> Option<&Self::Actor> { - match self.object_type() { - Some(ObjectType::Actor(_)) => Some(self), - _ => None, + fn as_actor(&self) -> Result<&Self::Actor, FieldErr> { + match self.object_type()? { + ObjectType::Actor(_) => Ok(self), + _ => Err(FieldErr("type")), } } - fn as_collection(&self) -> Option<&Self::Collection> { - match self.object_type() { - Some(ObjectType::Collection(_)) => Some(self), - _ => None, + fn as_collection(&self) -> Result<&Self::Collection, FieldErr> { + match self.object_type()? { + ObjectType::Collection(_) => Ok(self), + _ => Err(FieldErr("type")), } } - fn as_document(&self) -> Option<&Self::Document> { - match self.object_type() { - Some(ObjectType::Document(_)) => Some(self), - _ => None, + fn as_document(&self) -> Result<&Self::Document, FieldErr> { + match self.object_type()? { + ObjectType::Document(_) => Ok(self), + _ => Err(FieldErr("type")), } } } @@ -225,16 +225,16 @@ impl ObjectMut for serde_json::Value { crate::setter! { object_type -> type ObjectType } crate::setter! { attachment -> node ::Object } - crate::setter! { attributed_to::attributedTo -> node Self::Actor } + crate::setter! { attributedTo -> node Self::Actor } crate::setter! { audience -> node Self::Actor } crate::setter! { content -> &str } crate::setter! { context -> node ::Object } crate::setter! { name -> &str } - crate::setter! { end_time::endTime -> chrono::DateTime } + crate::setter! { endTime -> chrono::DateTime } crate::setter! { generator -> node Self::Actor } crate::setter! { icon -> node Self::Document } crate::setter! { image -> node Self::Document } - crate::setter! { in_reply_to::inReplyTo -> node ::Object } + crate::setter! { inReplyTo -> node ::Object } crate::setter! { location -> node ::Object } crate::setter! { preview -> node ::Object } crate::setter! { published -> chrono::DateTime } @@ -242,24 +242,24 @@ impl ObjectMut for serde_json::Value { crate::setter! { replies -> node Self::Collection } crate::setter! { likes -> node Self::Collection } crate::setter! { shares -> node Self::Collection } - crate::setter! { start_time::startTime -> chrono::DateTime } + crate::setter! { startTime -> chrono::DateTime } crate::setter! { summary -> &str } crate::setter! { tag -> node ::Object } crate::setter! { to -> node Self::Link } crate::setter! { bto -> node Self::Link} crate::setter! { cc -> 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! { url -> node Self::Link } #[cfg(feature = "activitypub-miscellaneous-terms")] crate::setter! { sensitive -> bool } #[cfg(feature = "activitypub-miscellaneous-terms")] - crate::setter! { quote_url::quoteUrl -> node ::Object } + crate::setter! { quoteUrl -> node ::Object } #[cfg(feature = "activitypub-fe")] - crate::setter! { liked_by_me::likedByMe -> bool } + crate::setter! { likedByMe -> bool } #[cfg(feature = "ostatus")] crate::setter! { conversation -> node ::Object } diff --git a/apb/src/types/object/place.rs b/apb/src/types/object/place.rs index 7fb9bada..eb4a4d28 100644 --- a/apb/src/types/object/place.rs +++ b/apb/src/types/object/place.rs @@ -1,10 +1,12 @@ +use crate::{Field, FieldErr}; + pub trait Place : super::Object { - fn accuracy(&self) -> Option { None } - fn altitude(&self) -> Option { None } - fn latitude(&self) -> Option { None } - fn longitude(&self) -> Option { None } - fn radius(&self) -> Option { None } - fn units(&self) -> Option<&str> { None } + fn accuracy(&self) -> Field { Err(FieldErr("accuracy")) } + fn altitude(&self) -> Field { Err(FieldErr("altitude")) } + fn latitude(&self) -> Field { Err(FieldErr("latitude")) } + fn longitude(&self) -> Field { Err(FieldErr("longitude")) } + fn radius(&self) -> Field { Err(FieldErr("radius")) } + fn units(&self) -> Field<&str> { Err(FieldErr("units")) } } pub trait PlaceMut : super::ObjectMut { diff --git a/apb/src/types/object/tombstone.rs b/apb/src/types/object/tombstone.rs index 97faf7c6..2c546e5f 100644 --- a/apb/src/types/object/tombstone.rs +++ b/apb/src/types/object/tombstone.rs @@ -1,6 +1,6 @@ pub trait Tombstone : super::Object { - fn former_type(&self) -> Option { None } - fn deleted(&self) -> Option> { None } + fn former_type(&self) -> crate::Field { Err(crate::FieldErr("formerType")) } + fn deleted(&self) -> crate::Field> { Err(crate::FieldErr("deleted")) } } pub trait TombstoneMut : super::ObjectMut {