diff --git a/apb/Cargo.toml b/apb/Cargo.toml index 0948974..2ca8916 100644 --- a/apb/Cargo.toml +++ b/apb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apb" -version = "0.1.0" +version = "0.1.1" edition = "2021" authors = [ "alemi " ] description = "Traits and types to handle ActivityPub objects" diff --git a/apb/README.md b/apb/README.md index dafd20a..e9e9c9a 100644 --- a/apb/README.md +++ b/apb/README.md @@ -3,13 +3,13 @@ `apb` implements all [ActivityStreams](https://www.w3.org/TR/activitystreams-core/) types as traits, so that implementing structs don't need to hold all possible fields, but only implement getters for relevant ones -`apb` also provides a `Node` enum, which can be Empty, Link, Object or Array +`apb` also provides a `Node` enum, which can represent ActivityPub nodes (empty, link, object, array) -if the `unstructured` feature is enabled, all traits are implemented for `serde_json::Value`, so that it's possible to manipulate free-form json maps as valid AP objects +read more in this crate's docs -if the `orm` feature is enabled, enum types are also database-friendly with sea-orm - -if the `fetch` feature is enabled (together with `unstructured`), `Node`s expose a `async fn fetch(&mut self) -> reqwest::Result<&mut Self>` to dereference remote nodes ## why -[upub](https://git.alemi.dev/upub.git) uses these types to implement its federation, but I wanted to modularize apb types. this crate is still work in progress and favors upub's needs, get in touch if you'd like to help or tune apb to your project! +[upub](https://git.alemi.dev/upub.git) uses these types to implement its federation, but I wanted to modularize apb types + +## state +this crate is still work in progress and favors upub's needs, get in touch if you'd like to help or tune apb to your project! diff --git a/apb/src/lib.rs b/apb/src/lib.rs index e689e46..3f72654 100644 --- a/apb/src/lib.rs +++ b/apb/src/lib.rs @@ -1,3 +1,92 @@ +//! # apb +//! > traits and types for implementing [ActivityPub](https://www.w3.org/TR/activitypub/) +//! +//! The main type this crate exposes is the [Node], which can be: +//! - [Node::Empty]: not present in object +//! - [Node::Link]: contains just link to object +//! - [Node::Object]: contains embedded object +//! - [Node::Array]: contains array of embedded objects +//! +//! Nodes contain AP objects, which implement one or more traits (such as [Object] or [Actor]) +//! +//! ## features +//! * `unstructured`: all traits are implemented for [serde_json::Value], so that it's possible to manipulate free-form json maps as valid AP objects +//! * `orm`: enum types are also database-friendly with sea-orm +//! * `fetch`: [Node] exposes [Node::fetch] to dereference remote nodes +//! +//! ## structure +//! - **[Base]** | **[BaseMut]** | [BaseType] +//! - [BaseType::Link] | **[Link]** | **[LinkMut]** | [LinkType] +//! - [LinkType::Mention] +//! - [LinkType::Link] +//! - [BaseType::Object] | **[Object]** | **[ObjectMut]** | [ObjectType] +//! - [ObjectType::Activity] | **[Activity]** | **[ActivityMut]** | [ActivityType] +//! - [ActivityType::Accept] | **[Accept]** | **[AcceptMut]** | [AcceptType] +//! - [AcceptType::TentativeAccept] +//! - [ActivityType::Add] +//! - [ActivityType::Announce] +//! - [ActivityType::Create] +//! - [ActivityType::Delete] +//! - [ActivityType::Dislike] +//! - [ActivityType::Flag] +//! - [ActivityType::Follow] +//! - [ActivityType::IntransitiveActivity] | **[IntransitiveActivity]** | **[IntransitiveActivityMut]** | [IntransitiveActivityType] +//! - [IntransitiveActivityType::IntransitiveActivity] +//! - [IntransitiveActivityType::Arrive] +//! - [IntransitiveActivityType::Question] +//! - [IntransitiveActivityType::Travel] +//! - [ActivityType::Ignore] | **[Ignore]** | **[IgnoreMut]** | [IgnoreType] +//! - [IgnoreType::Ignore] +//! - [IgnoreType::Block] +//! - [ActivityType::Join] +//! - [ActivityType::Leave] +//! - [ActivityType::Like] +//! - [ActivityType::Listen] +//! - [ActivityType::Move] +//! - [ActivityType::Offer] | **[Offer]** | **[OfferMut]** | [OfferType] +//! - [OfferType::Offer] +//! - [OfferType::Invite] +//! - [ActivityType::Read] +//! - [ActivityType::Reject] | **[Reject]** | **[RejectMut]** | [RejectType] +//! - [RejectType::Reject] +//! - [RejectType::TentativeReject] +//! - [ActivityType::Remove] +//! - [ActivityType::Undo] +//! - [ActivityType::Update] +//! - [ActivityType::View] +//! - [ObjectType::Actor] | **[Actor]** | **[ActorMut]** | [ActorType] * +//! - [ActorType::Application] +//! - [ActorType::Group] +//! - [ActorType::Organization] +//! - [ActorType::Person] +//! - [ObjectType::Article] +//! - [ObjectType::Collection] | **[Collection]** | **[CollectionMut]** | [CollectionType] +//! - [CollectionType::Collection] +//! - [CollectionType::CollectionPage] +//! - [CollectionType::OrderedCollection] +//! - [CollectionType::OrderedCollectionPage] +//! - [ObjectType::Document] | **[Document]** | **[DocumentMut]** | [DocumentType] +//! - [DocumentType::Document] +//! - [DocumentType::Audio] +//! - [DocumentType::Image] +//! - [DocumentType::Page] +//! - [DocumentType::Video] +//! - [ObjectType::Event] +//! - [ObjectType::Note] +//! - [ObjectType::Object] +//! - [ObjectType::Place] +//! - [ObjectType::Profile] +//! - [ObjectType::Relationship] +//! - [ObjectType::Tombstone] +//! - **[PublicKey]** | **[PublicKeyMut]** \*\* +//! +//! *: `Actor` is technically just an object, not really a "subtype" +//! +//! **: `PublicKey` is introduced in ActivityPub, it's not part of ActivityStream +//! + + + mod macros; pub(crate) use macros::{strenum, getter, setter}; diff --git a/apb/src/node.rs b/apb/src/node.rs index 9da4507..58411cd 100644 --- a/apb/src/node.rs +++ b/apb/src/node.rs @@ -1,3 +1,5 @@ +/// ActivityPub object node, representing either nothing, something, a link to something or +/// multiple things pub enum Node { Array(Vec), // TODO would be cool to make it Box<[T]> so that Node is just a ptr Object(Box), @@ -30,6 +32,7 @@ impl Iterator for Node { } impl Node { + /// return reference to embedded object (or last if many are present) pub fn get(&self) -> Option<&T> { match self { Node::Empty | Node::Link(_) => None, @@ -38,6 +41,7 @@ impl Node { } } + /// consume node and extract embedded object (or last if many are present) pub fn extract(self) -> Option { match self { Node::Empty | Node::Link(_) => None, @@ -46,22 +50,27 @@ impl Node { } } + /// true only if Node is empty pub fn is_empty(&self) -> bool { matches!(self, Node::Empty) } + /// true only if Node is link pub fn is_link(&self) -> bool { matches!(self, Node::Link(_)) } + /// true only if Node contains one embedded object pub fn is_object(&self) -> bool { matches!(self, Node::Object(_)) } + /// true only if Node contains many embedded objects pub fn is_array(&self) -> bool { matches!(self, Node::Array(_)) } + /// returns number of contained items (links count as items for len) pub fn len(&self) -> usize { match self { Node::Empty => 0, @@ -71,6 +80,7 @@ impl Node { } } + /// returns id of object: url for link, id for object, None if empty or array pub fn id(&self) -> Option { match self { Node::Empty | Node::Array(_) => None,