From e52b6a7fa7b3eba9617f7570a49724fd777caa65 Mon Sep 17 00:00:00 2001 From: asonix Date: Sun, 17 May 2020 14:35:10 -0500 Subject: [PATCH] Finish documenting, closes #1 --- README.md | 16 +- src/activity.rs | 406 +++++++++++++----------- src/actor.rs | 44 ++- src/base.rs | 16 + src/collection.rs | 794 +++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 29 +- src/link.rs | 14 + src/object.rs | 79 ++++- 8 files changed, 1172 insertions(+), 226 deletions(-) diff --git a/README.md b/README.md index 91d4586..37a5802 100644 --- a/README.md +++ b/README.md @@ -15,28 +15,20 @@ The project is laid out by Kind => vocabulary => Type So to use an ActivityStreams Video, you'd write ```rust use activitystreams_new::object::Video; -let video = Video::builder() - .inner(Default::default()) - .build(); +let video = Video::new(); ``` And to use an ActivityPub profile, you'd write ```rust use activitystreams_new::object::{ApObject, Profile}; -let inner = Profile::builder() - .inner(Default::default()) - .build(); -let profile = ApObject::builder() - .inner(inner) - .build(); +let inner = Profile::new(); +let profile = ApObject::new(inner); ``` There's only one kind of Link ```rust use activitystreams_new::link::Mention; -let mention = Mention::builder() - .inner(Default::default()) - .build(); +let mention = Mention::new(); ``` ### Fields diff --git a/src/activity.rs b/src/activity.rs index d03b208..e13a484 100644 --- a/src/activity.rs +++ b/src/activity.rs @@ -9,11 +9,10 @@ //! primitives::XsdAnyUri, //! }; //! -//! let mut create = Create::builder() -//! .object("https://example.com/notes/1234".parse::()?) -//! .actor("https://example.com/actors/abcd".parse::()?) -//! .inner(Default::default()) -//! .build(); +//! let mut create = Create::new( +//! "https://example.com/actors/abcd".parse::()?, +//! "https://example.com/notes/1234".parse::()?, +//! ); //! //! create //! .set_result("https://example.com/".parse::()?) @@ -421,11 +420,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Create}; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -448,11 +443,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create.set_actor("https://example.com".parse::()?); /// # Ok(()) @@ -478,11 +469,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create.set_many_actors(vec![ /// "https://example.com/one".parse::()?, @@ -513,11 +500,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create /// .add_actor("https://example.com/one".parse::()?) @@ -537,11 +520,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Create}; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -564,11 +543,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create.set_object("https://example.com".parse::()?); /// # Ok(()) @@ -594,11 +569,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create.set_many_objects(vec![ /// "https://example.com/one".parse::()?, @@ -629,11 +600,7 @@ pub trait ActorAndObjectRefExt: ActorAndObjectRef { /// # activity::Create, /// # primitives::XsdAnyUri /// # }; - /// # let mut create = Create::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut create = Create::new(context(), context()); /// /// create /// .add_object("https://example.com/one".parse::()?) @@ -658,12 +625,7 @@ pub trait TargetRefExt: TargetRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Invite}; - /// # let mut invite = Invite::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .target(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut invite = Invite::new(context(), context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -686,12 +648,7 @@ pub trait TargetRefExt: TargetRef { /// # activity::Invite, /// # primitives::XsdAnyUri /// # }; - /// # let mut invite = Invite::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .target(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut invite = Invite::new(context(), context(), context()); /// /// invite.set_target("https://example.com".parse::()?); /// # Ok(()) @@ -717,12 +674,7 @@ pub trait TargetRefExt: TargetRef { /// # activity::Invite, /// # primitives::XsdAnyUri /// # }; - /// # let mut invite = Invite::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .target(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut invite = Invite::new(context(), context(), context()); /// /// invite.set_many_targets(vec![ /// "https://example.com/one".parse::()?, @@ -753,12 +705,7 @@ pub trait TargetRefExt: TargetRef { /// # activity::Invite, /// # primitives::XsdAnyUri /// # }; - /// # let mut invite = Invite::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .target(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut invite = Invite::new(context(), context(), context()); /// /// invite /// .add_target("https://example.com/one".parse::()?) @@ -783,11 +730,7 @@ pub trait OriginRefExt: OriginRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Arrive}; - /// # let mut arrive = Arrive::builder() - /// # .actor(context()) - /// # .origin(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut arrive = Arrive::new(context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -810,11 +753,7 @@ pub trait OriginRefExt: OriginRef { /// # activity::Arrive, /// # primitives::XsdAnyUri /// # }; - /// # let mut arrive = Arrive::builder() - /// # .actor(context()) - /// # .origin(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut arrive = Arrive::new(context(), context()); /// /// arrive.set_origin("https://example.com".parse::()?); /// # Ok(()) @@ -840,11 +779,7 @@ pub trait OriginRefExt: OriginRef { /// # activity::Arrive, /// # primitives::XsdAnyUri /// # }; - /// # let mut arrive = Arrive::builder() - /// # .actor(context()) - /// # .origin(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut arrive = Arrive::new(context(), context()); /// /// arrive.set_many_origins(vec![ /// "https://example.com/one".parse::()?, @@ -875,11 +810,7 @@ pub trait OriginRefExt: OriginRef { /// # activity::Arrive, /// # primitives::XsdAnyUri /// # }; - /// # let mut arrive = Arrive::builder() - /// # .actor(context()) - /// # .origin(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut arrive = Arrive::new(context(), context()); /// /// arrive /// .add_origin("https://example.com/one".parse::()?) @@ -905,11 +836,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Announce}; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -933,11 +860,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// # activity::Announce, /// # primitives::XsdAnyUri /// # }; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// /// announce.set_target("https://example.com".parse::()?); /// # Ok(()) @@ -963,11 +886,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// # activity::Announce, /// # primitives::XsdAnyUri /// # }; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// /// announce.set_many_targets(vec![ /// "https://example.com/one".parse::()?, @@ -998,11 +917,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// # activity::Announce, /// # primitives::XsdAnyUri /// # }; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// /// announce /// .add_target("https://example.com/one".parse::()?) @@ -1035,11 +950,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// # activity::Announce, /// # primitives::XsdAnyUri /// # }; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// /// if let Some(target) = announce.take_target() { /// println!("{:?}", target); @@ -1061,11 +972,7 @@ pub trait OptTargetRefExt: OptTargetRef { /// # activity::Announce, /// # primitives::XsdAnyUri /// # }; - /// # let mut announce = Announce::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut announce = Announce::new(context(), context()); /// # announce.set_target(context()); /// /// assert!(announce.target().is_some()); @@ -1089,11 +996,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// /// ```rust /// # use activitystreams_new::{context, activity::Delete}; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// # /// use activitystreams_new::prelude::*; /// @@ -1117,11 +1020,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// # activity::Delete, /// # primitives::XsdAnyUri /// # }; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// /// delete.set_origin("https://example.com".parse::()?); /// # Ok(()) @@ -1147,11 +1046,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// # activity::Delete, /// # primitives::XsdAnyUri /// # }; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// /// delete.set_many_origins(vec![ /// "https://example.com/one".parse::()?, @@ -1182,11 +1077,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// # activity::Delete, /// # primitives::XsdAnyUri /// # }; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// /// delete /// .add_origin("https://example.com/one".parse::()?) @@ -1219,11 +1110,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// # activity::Delete, /// # primitives::XsdAnyUri /// # }; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// /// if let Some(origin) = delete.take_origin() { /// println!("{:?}", origin); @@ -1245,11 +1132,7 @@ pub trait OptOriginRefExt: OptOriginRef { /// # activity::Delete, /// # primitives::XsdAnyUri /// # }; - /// # let mut delete = Delete::builder() - /// # .actor(context()) - /// # .object(context()) - /// # .inner(Default::default()) - /// # .build(); + /// # let mut delete = Delete::new(context(), context()); /// # delete.set_origin(context()); /// /// assert!(delete.origin().is_some()); @@ -1544,7 +1427,7 @@ pub trait QuestionExt: AsQuestion { /// object has been accepted. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Accept that aren't already present on an Object. +/// Accept that aren't already present on an ActorAndObject. pub type Accept = ActorAndObject; /// Indicates that the actor has added the object to the target. @@ -1553,7 +1436,7 @@ pub type Accept = ActorAndObject; /// implicitly by context. The origin can be used to identify the context from which the object originated. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Add that aren't already present on an Object. +/// Add that aren't already present on an ActorAndObject. pub type Add = ActorAndObject; /// Indicates that the actor is blocking the object. @@ -1563,19 +1446,19 @@ pub type Add = ActorAndObject; /// defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Block that aren't already present on an Object. +/// Block that aren't already present on an ActorAndObject. pub type Block = ActorAndObject; /// Indicates that the actor has created the object. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Create that aren't already present on an Object. +/// Create that aren't already present on an ActorAndObject. pub type Create = ActorAndObject; /// Indicates that the actor dislikes the object. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Dislike that aren't already present on an Object. +/// Dislike that aren't already present on an ActorAndObject. pub type Dislike = ActorAndObject; /// Indicates that the actor is "flagging" the object. @@ -1584,7 +1467,7 @@ pub type Dislike = ActorAndObject; /// inappropriate for any number of reasons. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Flag that aren't already present on an Object. +/// Flag that aren't already present on an ActorAndObject. pub type Flag = ActorAndObject; /// Indicates that the actor is "following" the object. @@ -1594,7 +1477,7 @@ pub type Flag = ActorAndObject; /// no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to Follow -/// that aren't already present on an Object. +/// that aren't already present on an ActorAndObject. pub type Follow = ActorAndObject; /// Indicates that the actor is ignoring the object. @@ -1602,7 +1485,7 @@ pub type Follow = ActorAndObject; /// The target and origin typically have no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to Ignore -/// that aren't already present on an Object. +/// that aren't already present on an ActorAndObject. pub type Ignore = ActorAndObject; /// Indicates that the actor has joined the object. @@ -1610,7 +1493,7 @@ pub type Ignore = ActorAndObject; /// The target and origin typically have no defined meaning /// /// This is just an alias for `Object` because there's no fields inherent to Join that -/// aren't already present on an Object. +/// aren't already present on an ActorAndObject. pub type Join = ActorAndObject; /// Indicates that the actor has left the object. @@ -1618,7 +1501,7 @@ pub type Join = ActorAndObject; /// The target and origin typically have no meaning. /// /// This is just an alias for `Object` because there's no fields inherent to Leave that -/// aren't already present on an Object. +/// aren't already present on an ActorAndObject. pub type Leave = ActorAndObject; /// Indicates that the actor likes, recommends or endorses the object. @@ -1626,19 +1509,19 @@ pub type Leave = ActorAndObject; /// The target and origin typically have no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to Like that -/// aren't already present on an Object. +/// aren't already present on an ActorAndObject. pub type Like = ActorAndObject; /// Indicates that the actor has listened to the object. /// /// This is just an alias for `Object` because there's no fields inherent to Listen -/// that aren't already present on an Object. +/// that aren't already present on an ActorAndObject. pub type Listen = ActorAndObject; /// Indicates that the actor has read the object. /// /// This is just an alias for `Object` because there's no fields inherent to Read that -/// aren't already present on an Object. +/// aren't already present on an ActorAndObject. pub type Read = ActorAndObject; /// Indicates that the actor is rejecting the object. @@ -1646,19 +1529,19 @@ pub type Read = ActorAndObject; /// The target and origin typically have no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to Reject -/// that aren't already present on an Object. +/// that aren't already present on an ActorAndObject. pub type Reject = ActorAndObject; /// A specialization of Accept indicating that the acceptance is tentative. /// /// This is just an alias for `Object` because there's no fields inherent to -/// TentativeAccept that aren't already present on an Object. +/// TentativeAccept that aren't already present on an ActorAndObject. pub type TentativeAccept = ActorAndObject; /// A specialization of Reject in which the rejection is considered tentative. /// /// This is just an alias for `Object` because there's no fields inherent to -/// TentativeReject that aren't already present on an Object. +/// TentativeReject that aren't already present on an ActorAndObject. pub type TentativeReject = ActorAndObject; /// Indicates that the actor is undoing the object. @@ -1670,7 +1553,7 @@ pub type TentativeReject = ActorAndObject; /// The target and origin typically have no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Undo that aren't already present on an Object. +/// Undo that aren't already present on an ActorAndObject. pub type Undo = ActorAndObject; /// Indicates that the actor has updated the object. @@ -1681,13 +1564,13 @@ pub type Undo = ActorAndObject; /// The target and origin typically have no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Update that aren't already present on an Object. +/// Update that aren't already present on an ActorAndObject. pub type Update = ActorAndObject; /// Indicates that the actor has viewed the object. /// /// This is just an alias for `Object` because there's no fields inherent to -/// View that aren't already present on an Object. +/// View that aren't already present on an ActorAndObject. pub type View = ActorAndObject; /// Indicates that the actor is calling the target's attention the object. @@ -1695,7 +1578,7 @@ pub type View = ActorAndObject; /// The origin typically has no defined meaning. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Announce that aren't already present on an Object. +/// Announce that aren't already present on an ActorAndObjectOptTarget. pub type Announce = ActorAndObjectOptTarget; /// Indicates that the actor is offering the object. @@ -1703,7 +1586,7 @@ pub type Announce = ActorAndObjectOptTarget; /// If specified, the target indicates the entity to which the object is being offered. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Offer that aren't already present on an Object. +/// Offer that aren't already present on an ActorAndObjectOptTarget. pub type Offer = ActorAndObjectOptTarget; /// Indicates that the actor has moved object from origin to target. @@ -1711,7 +1594,7 @@ pub type Offer = ActorAndObjectOptTarget; /// If the origin or target are not specified, either can be determined by context. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Move that aren't already present on an Object. +/// Move that aren't already present on an ActorAndObjectOptOriginAndTarget. pub type Move = ActorAndObjectOptOriginAndTarget; /// Indicates that the actor is removing the object. @@ -1719,7 +1602,7 @@ pub type Move = ActorAndObjectOptOriginAndTarget; /// If specified, the origin indicates the context from which the object is being removed. /// /// This is just an alias for `Object` because there's no fields inherent to -/// Remove that aren't already present on an Object. +/// Remove that aren't already present on an ActorAndObjectOptOriginAndTarget. pub type Remove = ActorAndObjectOptOriginAndTarget; /// Activity objects are specializations of the base Object type that provide information about @@ -1788,9 +1671,6 @@ pub struct ActorAndObject { /// /// The origin can be used to identify the context from which the actor originated. The target /// typically has no defined meaning. -/// -/// This is just an alias for `Object` because there's no fields inherent to -/// Arrive that aren't already present on an Object. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -1824,9 +1704,6 @@ pub struct Arrive { /// A specialization of Offer in which the actor is extending an invitation for the object to the /// target. -/// -/// This is just an alias for `Object` because there's no fields inherent to -/// Invite that aren't already present on an Object. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -1872,9 +1749,6 @@ pub struct Invite { /// Indicates that the actor has deleted the object. /// /// If specified, the origin indicates the context from which the object was deleted. -/// -/// This is just an alias for `Object` because there's no fields inherent to -/// Delete that aren't already present on an Object. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -2021,9 +1895,6 @@ pub struct ActorAndObjectOptTarget { /// /// Travel is an IntransitiveObject whose actor specifies the direct object. If the target or /// origin are not specified, either can be determined by context. -/// -/// This is just an alias for `Object` because there's no fields inherent to -/// Travel that aren't already present on an Object. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -2077,9 +1948,6 @@ pub struct Travel { /// /// Either of the anyOf and oneOf properties MAY be used to express possible answers, but a /// Question object MUST NOT have both properties. -/// -/// This is just an alias for `Object` because there's no fields inherent to -/// Question that aren't already present on an Object. #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -2112,6 +1980,20 @@ pub struct Question { } impl Activity { + /// Create a new Activity + /// + /// ```rust + /// use activitystreams_new::activity::Activity; + /// + /// let activity = Activity::::new(); + /// ``` + pub fn new() -> Self + where + Kind: Default, + { + Activity::builder().inner(Object::new()).build() + } + fn extending(mut inner: Object) -> Result { let result = inner.remove("result")?; let instrument = inner.remove("instrument")?; @@ -2139,6 +2021,26 @@ impl Activity { } impl ActorAndObject { + /// Create a new ActorAndObject Activity + /// + /// ```rust + /// use activitystreams_new::activity::ActorAndObject; + /// + /// let activity = ActorAndObject::::new(vec![], vec![]); + /// ``` + pub fn new(actor: T, object: U) -> Self + where + T: Into>, + U: Into>, + Kind: Default, + { + Self::builder() + .actor(actor) + .object(object) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2166,6 +2068,25 @@ impl ActorAndObject { } impl Arrive { + /// Create a new Arrive Activity + /// + /// ```rust + /// use activitystreams_new::activity::Arrive; + /// + /// let activity = Arrive::new(vec![], vec![]); + /// ``` + pub fn new(actor: T, origin: U) -> Self + where + T: Into>, + U: Into>, + { + Self::builder() + .actor(actor) + .origin(origin) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2193,6 +2114,27 @@ impl Arrive { } impl Invite { + /// Create a new Invite Activity + /// + /// ```rust + /// use activitystreams_new::activity::Invite; + /// + /// let activity = Invite::new(vec![], vec![], vec![]); + /// ``` + pub fn new(actor: T, object: U, target: V) -> Self + where + T: Into>, + U: Into>, + V: Into>, + { + Self::builder() + .actor(actor) + .object(object) + .target(target) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2226,6 +2168,25 @@ impl Invite { } impl Delete { + /// Create a new Delete Activity + /// + /// ```rust + /// use activitystreams_new::activity::Delete; + /// + /// let activity = Delete::new(vec![], vec![]); + /// ``` + pub fn new(actor: T, object: U) -> Self + where + T: Into>, + U: Into>, + { + Self::builder() + .actor(actor) + .object(object) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2259,6 +2220,29 @@ impl Delete { } impl ActorAndObjectOptOriginAndTarget { + /// Create a new ActorAndObjectOptOriginAndTarget Activity + /// + /// ```rust + /// use activitystreams_new::activity::ActorAndObjectOptOriginAndTarget; + /// + /// let activity = ActorAndObjectOptOriginAndTarget::::new( + /// vec![], + /// vec![] + /// ); + /// ``` + pub fn new(actor: T, object: U) -> Self + where + T: Into>, + U: Into>, + Kind: Default, + { + Self::builder() + .actor(actor) + .object(object) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2296,6 +2280,29 @@ impl ActorAndObjectOptOriginAndTarget { } impl ActorAndObjectOptTarget { + /// Create a new ActorAndObjectOptTarget Activity + /// + /// ```rust + /// use activitystreams_new::activity::ActorAndObjectOptTarget; + /// + /// let activity = ActorAndObjectOptTarget::::new( + /// vec![], + /// vec![] + /// ); + /// ``` + pub fn new(actor: T, object: U) -> Self + where + T: Into>, + U: Into>, + Kind: Default, + { + Self::builder() + .actor(actor) + .object(object) + .inner(Activity::new()) + .build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2329,6 +2336,20 @@ impl ActorAndObjectOptTarget { } impl Travel { + /// Create a new Travel Activity + /// + /// ```rust + /// use activitystreams_new::activity::Travel; + /// + /// let activity = Travel::new(vec![]); + /// ``` + pub fn new(actor: T) -> Self + where + T: Into>, + { + Self::builder().actor(actor).inner(Activity::new()).build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; @@ -2362,6 +2383,17 @@ impl Travel { } impl Question { + /// Create a new Question Activity + /// + /// ```rust + /// use activitystreams_new::activity::Question; + /// + /// let activity = Question::new(); + /// ``` + pub fn new() -> Self { + Question::builder().inner(Activity::new()).build() + } + fn extending(object: Object) -> Result { let mut inner = Activity::extending(object)?; diff --git a/src/actor.rs b/src/actor.rs index 77e6f54..95904f8 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -620,7 +620,24 @@ pub type Person = Object; /// Service that aren't already present on an Object. pub type Service = Object; -/// Define activitypub properties for the Actor type as described by the Activity Pub vocabulary. +/// Actor types are Object types that are capable of performing activities. +/// +/// This specification intentionally defines Actors in only the most generalized way, stopping +/// short of defining semantically specific properties for each. All Actor objects are +/// specializations of Object and inherit all of the core properties common to all Objects. +/// External vocabularies can be used to express additional detail not covered by the Activity +/// Vocabulary. VCard [vcard-rdf SHOULD be used to provide additional metadata for Person, Group, +/// and Organization instances. +/// +/// While implementations are free to introduce new types of Actors beyond those defined by the +/// Activity Vocabulary, interoperability issues can arise when applications rely too much on +/// extension types that are not recognized by other implementations. Care should be taken to not +/// unduly overlap with or duplicate the existing Actor types. +/// +/// When an implementation uses an extension type that overlaps with a core vocabulary type, the +/// implementation MUST also specify the core vocabulary type. For instance, some vocabularies +/// (e.g. VCard) define their own types for describing people. An implementation that wishes, for +/// example, to use a vcard:Individual as an Actor MUST also identify that Actor as a Person. #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] @@ -773,6 +790,31 @@ pub struct Endpoints { } impl ApActor { + /// Create a new ActivityPub Actor + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// use activitystreams_new::actor::{ApActor, Person}; + /// + /// let actor = ApActor::new( + /// "https://example.com/inbox".parse()?, + /// "https://example.com/outbox".parse()?, + /// Person::new(), + /// ); + /// # Ok(()) + /// # } + /// ``` + pub fn new(inbox: XsdAnyUri, outbox: XsdAnyUri, inner: Inner) -> Self + where + Inner: markers::Actor, + { + Self::builder() + .inbox(inbox) + .outbox(outbox) + .inner(inner) + .build() + } + fn extending(mut inner: Inner) -> Result where Inner: UnparsedMut + markers::Actor, diff --git a/src/base.rs b/src/base.rs index ba2c0cb..d2386ec 100644 --- a/src/base.rs +++ b/src/base.rs @@ -851,6 +851,20 @@ impl Base { } impl Base { + /// Create a new Base + /// + /// ```rust + /// use activitystreams_new::base::Base; + /// + /// let base = Base::::new(); + /// ``` + pub fn new() -> Self + where + Kind: Default, + { + Base::builder().kind(Kind::default()).build() + } + /// Extend the Base into any other ActivityStreams type provided in this crate /// /// ```rust @@ -1036,6 +1050,7 @@ impl AnyBase { /// This method checks if the current object _is_ an ID, and then falls back on the `id` field /// within the `Base` if that exists /// + /// #### Get the ID from the nested video /// ```rust /// # fn main() -> Result<(), anyhow::Error> { /// # use activitystreams_new::{ @@ -1052,6 +1067,7 @@ impl AnyBase { /// # } /// ``` /// + /// #### Get the ID from the AnyBase /// ```rust /// # fn main() -> Result<(), anyhow::Error> { /// # use activitystreams_new::{ diff --git a/src/collection.rs b/src/collection.rs index 8b04489..6890623 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -1,3 +1,31 @@ +//! Types and traits for dealing with Collection attributes +//! +//! ```rust +//! # fn main() -> Result<(), anyhow::Error> { +//! use activitystreams_new::{ +//! collection::OrderedCollection, +//! context, +//! prelude::*, +//! primitives::XsdAnyUri, +//! }; +//! +//! let mut collection = OrderedCollection::builder() +//! .items(vec![ +//! "https://example.com/notes/1234".parse::()?.into(), +//! ]) +//! .inner(Default::default()) +//! .build(); +//! +//! collection +//! .set_total_items(1) +//! .set_current("https://example.com/notes/1234".parse::()?) +//! .set_first("https://example.com/notes/1234".parse::()?) +//! .set_last("https://example.com/notes/1234".parse::()?) +//! .set_id("https://example.com/collections/1234".parse()?) +//! .set_context(context()); +//! # Ok(()) +//! # } +//! ``` use crate::{ base::{AnyBase, AsBase, Base, Extends}, markers, @@ -9,27 +37,59 @@ use std::convert::TryFrom; use typed_builder::TypedBuilder; pub mod kind { + //! Kinds of collections defined by the spec + //! + //! These types exist only to be statically-typed versions of the associated string. e.g. + //! `CollectionType` -> `"Collection"` + pub use activitystreams::collection::kind::*; } use self::kind::*; +/// Implementation trait for deriving Collection methods for a type +/// +/// Any type implementing AsCollection will automatically gain methods provided by CollectionExt pub trait AsCollection: markers::Collection { fn collection_ref(&self) -> &Collection; fn collection_mut(&mut self) -> &mut Collection; } +/// Implementation trait for deriving Collection methods for a type +/// +/// Any type implementing AsCollectionPage will automatically gain methods provided by CollectionPageExt pub trait AsCollectionPage: markers::CollectionPage { fn collection_page_ref(&self) -> &CollectionPage; fn collection_page_mut(&mut self) -> &mut CollectionPage; } +/// Implementation trait for deriving Collection methods for a type +/// +/// Any type implementing AsOrderedCollectionPage will automatically gain methods provided by +/// OrderedCollectionPageExt pub trait AsOrderedCollectionPage: markers::CollectionPage { fn ordered_collection_page_ref(&self) -> &OrderedCollectionPage; fn ordered_collection_page_mut(&mut self) -> &mut OrderedCollectionPage; } +/// Helper methods for interacting with Collection types +/// +/// This trait represents methods valid for any ActivityStreams Collection +/// +/// Documentation for the fields related to these methods can be found on the +/// `Collection` struct pub trait CollectionExt: AsCollection { + /// Fetch the items for the current activity + /// + /// ```rust + /// # use activitystreams_new::{context, collection::UnorderedCollection}; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// let items_ref = collection.items(); + /// println!("{:?}", items_ref); + /// ``` fn items<'a>(&'a self) -> &'a OneOrMany where Kind: 'a, @@ -37,6 +97,24 @@ pub trait CollectionExt: AsCollection { &self.collection_ref().items } + /// Set the items for the current activity + /// + /// This overwrites the contents of items + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// use activitystreams_new::prelude::*; + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// + /// collection.set_items("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_items(&mut self, item: T) -> &mut Self where T: Into, @@ -45,6 +123,27 @@ pub trait CollectionExt: AsCollection { self } + /// Set many itemss for the current activity + /// + /// This overwrites the contents of items + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// use activitystreams_new::prelude::*; + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// + /// collection.set_many_items(vec![ + /// "https://example.com/one".parse::()?, + /// "https://example.com/two".parse()?, + /// ]); + /// # Ok(()) + /// # } + /// ``` fn set_many_items(&mut self, items: I) -> &mut Self where I: IntoIterator, @@ -55,7 +154,27 @@ pub trait CollectionExt: AsCollection { self } - fn add_item(&mut self, item: T) -> &mut Self + /// Add a items to the current activity + /// + /// This does not overwrite the contents of items, only appends an item + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// use activitystreams_new::prelude::*; + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// + /// collection + /// .add_items("https://example.com/one".parse::()?) + /// .add_items("https://example.com/two".parse::()?); + /// # Ok(()) + /// # } + /// ``` + fn add_items(&mut self, item: T) -> &mut Self where T: Into, { @@ -63,6 +182,21 @@ pub trait CollectionExt: AsCollection { self } + /// Fetch the total_items of the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// if let Some(total_items) = collection.total_items() { + /// println!("{:?}", total_items); + /// } + /// ``` fn total_items<'a>(&'a self) -> Option<&'a XsdNonNegativeInteger> where Kind: 'a, @@ -70,6 +204,21 @@ pub trait CollectionExt: AsCollection { self.collection_ref().total_items.as_ref() } + /// Set the total_items for the current object + /// + /// This overwrites the contents of total_items + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// collection.set_total_items(5); + /// ``` fn set_total_items(&mut self, total_items: T) -> &mut Self where T: Into, @@ -78,15 +227,62 @@ pub trait CollectionExt: AsCollection { self } + /// Take the total_items of the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// if let Some(total_items) = collection.total_items() { + /// println!("{:?}", total_items); + /// } + /// ``` fn take_total_items(&mut self) -> Option { self.collection_mut().total_items.take() } + /// Delete the total_items from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # collection.set_total_items(5); + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.total_items().is_some()); + /// collection.delete_total_items(); + /// assert!(collection.total_items().is_none()); + /// ``` fn delete_total_items(&mut self) -> &mut Self { self.collection_mut().total_items = None; self } + /// Fetch the current field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(current) = collection.current() { + /// println!("{:?}", current); + /// } + /// ``` fn current<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -94,6 +290,25 @@ pub trait CollectionExt: AsCollection { self.collection_ref().current.as_ref() } + /// Set the current field for the current object + /// + /// This overwrites the contents of current + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_current("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_current(&mut self, current: T) -> &mut Self where T: Into, @@ -102,15 +317,64 @@ pub trait CollectionExt: AsCollection { self } + /// Take the current field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(current) = collection.take_current() { + /// println!("{:?}", current); + /// } + /// ``` fn take_current(&mut self) -> Option { self.collection_mut().current.take() } + /// Delete the current field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # collection.set_current(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.current().is_some()); + /// collection.delete_current(); + /// assert!(collection.current().is_none()); + /// ``` fn delete_current(&mut self) -> &mut Self { self.collection_mut().current = None; self } + /// Fetch the first field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(first) = collection.first() { + /// println!("{:?}", first); + /// } + /// ``` fn first<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -118,6 +382,25 @@ pub trait CollectionExt: AsCollection { self.collection_ref().first.as_ref() } + /// Set the first field for the current object + /// + /// This overwrites the contents of first + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_first("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_first(&mut self, first: T) -> &mut Self where T: Into, @@ -126,15 +409,64 @@ pub trait CollectionExt: AsCollection { self } + /// Take the first field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(first) = collection.take_first() { + /// println!("{:?}", first); + /// } + /// ``` fn take_first(&mut self) -> Option { self.collection_mut().first.take() } + /// Delete the first field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # collection.set_first(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.first().is_some()); + /// collection.delete_first(); + /// assert!(collection.first().is_none()); + /// ``` fn delete_first(&mut self) -> &mut Self { self.collection_mut().first = None; self } + /// Fetch the last field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(last) = collection.last() { + /// println!("{:?}", last); + /// } + /// ``` fn last<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -142,6 +474,25 @@ pub trait CollectionExt: AsCollection { self.collection_ref().last.as_ref() } + /// Set the last field for the current object + /// + /// This overwrites the contents of last + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_last("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_last(&mut self, last: T) -> &mut Self where T: Into, @@ -150,17 +501,72 @@ pub trait CollectionExt: AsCollection { self } + /// Take the last field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(last) = collection.take_last() { + /// println!("{:?}", last); + /// } + /// ``` fn take_last(&mut self) -> Option { self.collection_mut().last.take() } + /// Delete the last field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollection, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollection::new(vec![context().into()]); + /// # collection.set_last(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.last().is_some()); + /// collection.delete_last(); + /// assert!(collection.last().is_none()); + /// ``` fn delete_last(&mut self) -> &mut Self { self.collection_mut().last = None; self } } +/// Helper methods for interacting with CollectionPage types +/// +/// This trait represents methods valid for any ActivityStreams CollectionPage +/// +/// Documentation for the fields related to these methods can be found on the +/// `CollectionPage` struct pub trait CollectionPageExt: AsCollectionPage { + /// Fetch the part_of field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(part_of) = collection.part_of() { + /// println!("{:?}", part_of); + /// } + /// ``` fn part_of<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -168,6 +574,25 @@ pub trait CollectionPageExt: AsCollectionPage { self.collection_page_ref().part_of.as_ref() } + /// Set the part_of field for the current object + /// + /// This overwrites the contents of part_of + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_part_of("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_part_of(&mut self, part_of: T) -> &mut Self where T: Into, @@ -176,15 +601,64 @@ pub trait CollectionPageExt: AsCollectionPage { self } + /// Take the part_of field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(part_of) = collection.take_part_of() { + /// println!("{:?}", part_of); + /// } + /// ``` fn take_part_of(&mut self) -> Option { self.collection_page_mut().part_of.take() } + /// Delete the part_of field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # collection.set_part_of(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.part_of().is_some()); + /// collection.delete_part_of(); + /// assert!(collection.part_of().is_none()); + /// ``` fn delete_part_of(&mut self) -> &mut Self { self.collection_page_mut().part_of = None; self } + /// Fetch the next field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(next) = collection.next() { + /// println!("{:?}", next); + /// } + /// ``` fn next<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -192,6 +666,25 @@ pub trait CollectionPageExt: AsCollectionPage { self.collection_page_ref().next.as_ref() } + /// Set the next field for the current object + /// + /// This overwrites the contents of next + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_next("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_next(&mut self, next: T) -> &mut Self where T: Into, @@ -200,15 +693,64 @@ pub trait CollectionPageExt: AsCollectionPage { self } + /// Take the next field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(next) = collection.take_next() { + /// println!("{:?}", next); + /// } + /// ``` fn take_next(&mut self) -> Option { self.collection_page_mut().next.take() } + /// Delete the next field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # collection.set_next(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.next().is_some()); + /// collection.delete_next(); + /// assert!(collection.next().is_none()); + /// ``` fn delete_next(&mut self) -> &mut Self { self.collection_page_mut().next = None; self } + /// Fetch the prev field for the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(prev) = collection.prev() { + /// println!("{:?}", prev); + /// } + /// ``` fn prev<'a>(&'a self) -> Option<&'a AnyBase> where Kind: 'a, @@ -216,6 +758,25 @@ pub trait CollectionPageExt: AsCollectionPage { self.collection_page_ref().prev.as_ref() } + /// Set the prev field for the current object + /// + /// This overwrites the contents of prev + /// + /// ```rust + /// # fn main() -> Result<(), anyhow::Error> { + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// collection.set_prev("https://example.com".parse::()?); + /// # Ok(()) + /// # } + /// ``` fn set_prev(&mut self, prev: T) -> &mut Self where T: Into, @@ -224,10 +785,43 @@ pub trait CollectionPageExt: AsCollectionPage { self } + /// Take the prev field from the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # + /// use activitystreams_new::prelude::*; + /// + /// if let Some(prev) = collection.take_prev() { + /// println!("{:?}", prev); + /// } + /// ``` fn take_prev(&mut self) -> Option { self.collection_page_mut().prev.take() } + /// Delete the prev field from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::UnorderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = UnorderedCollectionPage::new(vec![context().into()]); + /// # collection.set_prev(context()); + /// # + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.prev().is_some()); + /// collection.delete_prev(); + /// assert!(collection.prev().is_none()); + /// ``` fn delete_prev(&mut self) -> &mut Self { self.collection_page_mut().prev = None; self @@ -235,10 +829,40 @@ pub trait CollectionPageExt: AsCollectionPage { } pub trait OrderedCollectionPageExt: AsOrderedCollectionPage { + /// Fetch the start_index of the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::OrderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = OrderedCollectionPage::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// if let Some(start_index) = collection.start_index() { + /// println!("{:?}", start_index); + /// } + /// ``` fn start_index(&self) -> Option<&XsdNonNegativeInteger> { self.ordered_collection_page_ref().start_index.as_ref() } + /// Set the start_index for the current object + /// + /// This overwrites the contents of start_index + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::OrderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = OrderedCollectionPage::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// collection.set_start_index(5); + /// ``` fn set_start_index(&mut self, start_index: T) -> &mut Self where T: Into, @@ -247,80 +871,199 @@ pub trait OrderedCollectionPageExt: AsOrderedCollectionPage { self } + /// Take the start_index of the current object, leaving nothing + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::OrderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = OrderedCollectionPage::new(vec![context().into()]); + /// use activitystreams_new::prelude::*; + /// + /// if let Some(start_index) = collection.start_index() { + /// println!("{:?}", start_index); + /// } + /// ``` fn take_start_index(&mut self) -> Option { self.ordered_collection_page_mut().start_index.take() } + /// Delete the start_index from the current object + /// + /// ```rust + /// # use activitystreams_new::{ + /// # context, + /// # collection::OrderedCollectionPage, + /// # primitives::XsdAnyUri + /// # }; + /// # let mut collection = OrderedCollectionPage::new(vec![context().into()]); + /// # collection.set_start_index(5); + /// use activitystreams_new::prelude::*; + /// + /// assert!(collection.start_index().is_some()); + /// collection.delete_start_index(); + /// assert!(collection.start_index().is_none()); + /// ``` fn delete_start_index(&mut self) -> &mut Self { self.ordered_collection_page_mut().start_index = None; self } } +/// A subtype of Collection in which members of the logical collection are assumed to always be +/// strictly ordered. +/// +/// This is just an alias for `Collection` because there's no fields +/// inherent to UnorderedCollection that aren't already present on a Collection. pub type OrderedCollection = Collection; + +/// The default Collection type. +/// +/// This is just an alias for `Collection` because there's no fields +/// inherent to UnorderedCollection that aren't already present on a Collection. pub type UnorderedCollection = Collection; + +/// Used to represent distinct subsets of items from a Collection. +/// +/// This is just an alias for `CollectionPage` because there's no fields +/// inherent to UnorderedCollection that aren't already present on a CollectionPage. pub type UnorderedCollectionPage = CollectionPage; +/// A Collection is a subtype of Object that represents ordered or unordered sets of Object or Link +/// instances. +/// +/// The items within a Collection can be ordered or unordered. The OrderedCollection type MAY be +/// used to identify a Collection whose items are always ordered. In the JSON serialization, the +/// unordered items of a Collection are represented using the items property while ordered items +/// are represented using the orderedItems property. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] pub struct Collection { + /// Identifies the items contained in a collection. The items might be ordered or unordered. + /// + /// - Range: Object | Link | Ordered List of [ Object | Link ] + /// - Functional: false #[builder(setter(into))] pub items: OneOrMany, + /// A non-negative integer specifying the total number of objects contained by the logical view + /// of the collection. + /// + /// This number might not reflect the actual number of items serialized within the Collection + /// object instance. + /// + /// - Range: xsd:nonNegativeInteger + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub total_items: Option, + /// In a paged Collection, indicates the page that contains the most recently updated member + /// items. + /// + /// - Range: CollectionPage | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub current: Option, + /// In a paged Collection, indicates the furthest preceeding page of items in the collection. + /// + /// - Range: CollectionPage | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub first: Option, + /// In a paged Collection, indicates the furthest proceeding page of the collection. + /// + /// - Range: CollectionPage | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub last: Option, + /// Base fields and unparsed json ends up here #[serde(flatten)] pub inner: Object, } +/// Used to represent distinct subsets of items from a Collection. +/// +/// A Collection can contain a large number of items. Often, it becomes impractical for an +/// implementation to serialize every item contained by a Collection using the items (or +/// ordered_items) property alone. In such cases, the items within a Collection can be divided into +/// distinct subsets or "pages". A page is identified using the CollectionPage type. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] pub struct CollectionPage { + /// Identifies the Collection to which a CollectionPage objects items belong. + /// + /// - Range: Collection | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub part_of: Option, + /// In a paged Collection, indicates the next page of items. + /// + /// - Range: CollectionPage | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub next: Option, + /// In a paged Collection, identifies the previous page of items. + /// + /// - Range: CollectionPage | Link + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub prev: Option, + /// Base fields and unparsed json ends up here #[serde(flatten)] pub inner: Collection, } +/// Used to represent ordered subsets of items from an OrderedCollection. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] pub struct OrderedCollectionPage { + /// A non-negative integer value identifying the relative position within the logical view of a strictly ordered collection. + /// + /// - Range: xsd:nonNegativeInteger + /// - Functional: true #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub start_index: Option, + /// Base fields and unparsed json ends up here #[serde(flatten)] pub inner: CollectionPage, } impl Collection { + /// Create a new Collection + /// + /// ```rust + /// use activitystreams_new::collection::Collection; + /// + /// let collection = Collection::::new(vec![]); + /// ``` + pub fn new(items: T) -> Self + where + T: Into>, + Kind: Default, + { + Self::builder().items(items).inner(Object::new()).build() + } + fn extending(mut inner: Object) -> Result { let items = inner.remove("items")?; let total_items = inner.remove("totalItems")?; @@ -360,6 +1103,23 @@ impl Collection { } impl CollectionPage { + /// Create a new CollectionPage + /// + /// ```rust + /// use activitystreams_new::collection::CollectionPage; + /// + /// let collection = CollectionPage::::new(vec![]); + /// ``` + pub fn new(items: T) -> Self + where + T: Into>, + Kind: Default, + { + let collection = Collection::new(items); + + CollectionPage::builder().inner(collection).build() + } + fn extending(object: Object) -> Result { let mut inner = Collection::extending(object)?; @@ -393,6 +1153,24 @@ impl CollectionPage { } impl OrderedCollectionPage { + /// Create a new CollectionPage + /// + /// ```rust + /// use activitystreams_new::collection::OrderedCollectionPage; + /// + /// let collection = OrderedCollectionPage::new(vec![]); + /// ``` + pub fn new(items: T) -> Self + where + T: Into>, + { + let collection_page = CollectionPage::new(items); + + OrderedCollectionPage::builder() + .inner(collection_page) + .build() + } + fn extending(object: Object) -> Result { let mut inner = CollectionPage::extending(object)?; @@ -427,6 +1205,9 @@ impl markers::Object for OrderedCollectionPage {} impl markers::Collection for OrderedCollectionPage {} impl markers::CollectionPage for OrderedCollectionPage {} +impl markers::Collection for ApObject where Inner: markers::Collection {} +impl markers::CollectionPage for ApObject where Inner: markers::CollectionPage {} + impl Extends for Collection where Kind: serde::de::DeserializeOwned + serde::ser::Serialize, @@ -651,8 +1432,15 @@ impl AsCollectionPage for OrderedCollectionPage { } } -impl markers::Collection for ApObject where Inner: markers::Collection {} -impl markers::CollectionPage for ApObject where Inner: markers::CollectionPage {} +impl AsOrderedCollectionPage for OrderedCollectionPage { + fn ordered_collection_page_ref(&self) -> &OrderedCollectionPage { + self + } + + fn ordered_collection_page_mut(&mut self) -> &mut OrderedCollectionPage { + self + } +} impl AsCollection for ApObject where diff --git a/src/lib.rs b/src/lib.rs index 8a8be4d..c2342b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,28 +15,20 @@ //! So to use an ActivityStreams Video, you'd write //! ```rust //! use activitystreams_new::object::Video; -//! let video = Video::builder() -//! .inner(Default::default()) -//! .build(); +//! let video = Video::new(); //! ``` //! //! And to use an ActivityPub profile, you'd write //! ```rust //! use activitystreams_new::object::{ApObject, Profile}; -//! let inner = Profile::builder() -//! .inner(Default::default()) -//! .build(); -//! let profile = ApObject::builder() -//! .inner(inner) -//! .build(); +//! let inner = Profile::new(); +//! let profile = ApObject::new(inner); //! ``` //! //! There's only one kind of Link //! ```rust //! use activitystreams_new::link::Mention; -//! let mention = Mention::builder() -//! .inner(Default::default()) -//! .build(); +//! let mention = Mention::new(); //! ``` //! //! ### Fields @@ -304,7 +296,6 @@ pub mod prelude { //! //! let mut person = ApActor::::default(); //! person - //! .set_kind(PersonType) //! .set_inbox("https://localhost:8080/inbox".parse()?) //! .set_outbox("https://localhost:8080/outbox".parse()?) //! .set_name(XsdString::from("Demo Account")) @@ -315,7 +306,6 @@ pub mod prelude { //! let mut preview = Image::default(); //! //! preview - //! .set_kind(ImageType) //! .set_url("https://localhost:8080/preview.png".parse::()?) //! .set_media_type("image/png".parse()?) //! .set_id("https://localhostst:8080/preview.png".parse()?); @@ -323,7 +313,6 @@ pub mod prelude { //! let mut video = ApObject::