docs: document crate a little

This commit is contained in:
əlemi 2024-04-06 19:16:15 +02:00
parent 863b17b363
commit 9d3376a1f4
Signed by: alemi
GPG key ID: A4895B84D311642C
4 changed files with 106 additions and 7 deletions

View file

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

View file

@ -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` 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<T>` 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 ## 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!

View file

@ -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; mod macros;
pub(crate) use macros::{strenum, getter, setter}; pub(crate) use macros::{strenum, getter, setter};

View file

@ -1,3 +1,5 @@
/// ActivityPub object node, representing either nothing, something, a link to something or
/// multiple things
pub enum Node<T : super::Base> { pub enum Node<T : super::Base> {
Array(Vec<T>), // TODO would be cool to make it Box<[T]> so that Node is just a ptr Array(Vec<T>), // TODO would be cool to make it Box<[T]> so that Node is just a ptr
Object(Box<T>), Object(Box<T>),
@ -30,6 +32,7 @@ impl<T : super::Base + Clone> Iterator for Node<T> {
} }
impl<T : super::Base> Node<T> { impl<T : super::Base> Node<T> {
/// return reference to embedded object (or last if many are present)
pub fn get(&self) -> Option<&T> { pub fn get(&self) -> Option<&T> {
match self { match self {
Node::Empty | Node::Link(_) => None, Node::Empty | Node::Link(_) => None,
@ -38,6 +41,7 @@ impl<T : super::Base> Node<T> {
} }
} }
/// consume node and extract embedded object (or last if many are present)
pub fn extract(self) -> Option<T> { pub fn extract(self) -> Option<T> {
match self { match self {
Node::Empty | Node::Link(_) => None, Node::Empty | Node::Link(_) => None,
@ -46,22 +50,27 @@ impl<T : super::Base> Node<T> {
} }
} }
/// true only if Node is empty
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
matches!(self, Node::Empty) matches!(self, Node::Empty)
} }
/// true only if Node is link
pub fn is_link(&self) -> bool { pub fn is_link(&self) -> bool {
matches!(self, Node::Link(_)) matches!(self, Node::Link(_))
} }
/// true only if Node contains one embedded object
pub fn is_object(&self) -> bool { pub fn is_object(&self) -> bool {
matches!(self, Node::Object(_)) matches!(self, Node::Object(_))
} }
/// true only if Node contains many embedded objects
pub fn is_array(&self) -> bool { pub fn is_array(&self) -> bool {
matches!(self, Node::Array(_)) matches!(self, Node::Array(_))
} }
/// returns number of contained items (links count as items for len)
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
match self { match self {
Node::Empty => 0, Node::Empty => 0,
@ -71,6 +80,7 @@ impl<T : super::Base> Node<T> {
} }
} }
/// returns id of object: url for link, id for object, None if empty or array
pub fn id(&self) -> Option<String> { pub fn id(&self) -> Option<String> {
match self { match self {
Node::Empty | Node::Array(_) => None, Node::Empty | Node::Array(_) => None,