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 8486c17..0276874 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 8a7f6e2..fe41f8b 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 00afef1..bf0feb4 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 2d05f3e..dd062aa 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 a1312e4..506b749 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 e76a53a..0000000 --- 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 79a8a41..f4096f5 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 e992435..44b271e 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 774be39..ec8a427 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 93c35aa..45a42fb 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 f3688bb..8162e5b 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 d742cbf..c7e792f 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 90c12eb..81b9506 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 92cf8b6..a84b25f 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 ed18ffa..a295a9a 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 9bd8757..98788a4 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 92d961f..86f9295 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 a7b1361..9df31a5 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 85ec286..95a7f08 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 749f99c..50ab2ae 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 7fb9bad..eb4a4d2 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 97faf7c..2c546e5 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 {