//! # An extension API for activitystreams //! _This crate provides Ext1, Ext2, Ext3, and Ext4 for adding extensions to ActivityStreams types_ //! //! - Find the code on [git.asonix.dog](https://git.asonix.dog/Aardwolf/activitystreams) //! - Read the docs on [docs.rs](https://docs.rs/activitystreams-ext) //! - Join the matrix channel at [#activitypub:asonix.dog](https://matrix.to/#/!fAEcHyTUdAaKCzIKCt:asonix.dog?via=asonix.dog&via=matrix.org&via=t2bot.io) //! - Hit me up on [mastodon](https://asonix.dog/@asonix) //! //! ## Usage //! //! First, add ActivityStreams to your dependencies //! ```toml //! [dependencies] //! activitystreams = "0.7.0-alpha.3" //! activitystreams-ext = "0.1.0-alpha.2" //! ``` //! //! For an example, we'll implement a PublicKey extension and demonstrate usage with Ext1 //! ```rust //! use activitystreams::{ //! actor::{ApActor, Person}, //! context, //! prelude::*, //! security, //! unparsed::UnparsedMutExt, //! url::Url, //! }; //! use activitystreams_ext::{Ext1, UnparsedExtension}; //! //! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] //! #[serde(rename_all = "camelCase")] //! pub struct PublicKey { //! public_key: PublicKeyInner, //! } //! //! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] //! #[serde(rename_all = "camelCase")] //! pub struct PublicKeyInner { //! id: Url, //! owner: Url, //! public_key_pem: String, //! } //! //! impl UnparsedExtension for PublicKey //! where //! U: UnparsedMutExt, //! { //! type Error = serde_json::Error; //! //! fn try_from_unparsed(unparsed_mut: &mut U) -> Result { //! Ok(PublicKey { //! public_key: unparsed_mut.remove("publicKey")?, //! }) //! } //! //! fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> { //! unparsed_mut.insert("publicKey", self.public_key)?; //! Ok(()) //! } //! } //! //! pub type ExtendedPerson = Ext1, PublicKey>; //! //! fn main() -> Result<(), anyhow::Error> { //! let actor = ApActor::new("http://in.box".parse()?, Person::new()); //! //! let mut person = Ext1::new( //! actor, //! PublicKey { //! public_key: PublicKeyInner { //! id: "http://key.id".parse()?, //! owner: "http://owner.id".parse()?, //! public_key_pem: "asdfasdfasdf".to_owned(), //! }, //! }, //! ); //! //! person.set_context(context()).add_context(security()); //! //! let any_base = person.into_any_base()?; //! println!("any_base: {:#?}", any_base); //! let person = ExtendedPerson::from_any_base(any_base)?; //! //! println!("person: {:#?}", person); //! Ok(()) //! } //! ``` #![doc(html_root_url = "https://docs.rs/activitystreams-ext/0.1.0-alpha.0/activitystreams_ext")] use activitystreams::{ base::{Base, Extends}, unparsed::{UnparsedMut, UnparsedMutExt}, }; mod ext1; mod ext2; mod ext3; mod ext4; /// Transform types from and into the Unparsed structure pub trait UnparsedExtension where U: UnparsedMutExt, { type Error: std::error::Error; /// Generate Self from Unparsed fn try_from_unparsed(unparsed_mut: &mut U) -> Result where Self: Sized; /// Insert Self into Unparsed fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error>; } /// Extend a type with a single value #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct Ext1 { #[serde(flatten)] pub ext_one: A, /// The type being extended #[serde(flatten)] pub inner: Inner, } /// Extend a type with two values #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct Ext2 { #[serde(flatten)] pub ext_one: A, #[serde(flatten)] pub ext_two: B, /// The type being extended #[serde(flatten)] pub inner: Inner, } /// Extend a type with three values #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct Ext3 { #[serde(flatten)] pub ext_one: A, #[serde(flatten)] pub ext_two: B, #[serde(flatten)] pub ext_three: C, /// The type being extended #[serde(flatten)] pub inner: Inner, } /// Extend a type with four values #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct Ext4 { #[serde(flatten)] pub ext_one: A, #[serde(flatten)] pub ext_two: B, #[serde(flatten)] pub ext_three: C, #[serde(flatten)] pub ext_four: D, /// The type being extended #[serde(flatten)] pub inner: Inner, } impl Ext1 { pub fn new(inner: Inner, ext_one: A) -> Self { Ext1 { inner, ext_one } } pub fn into_parts(self) -> (Inner, A) { (self.inner, self.ext_one) } pub fn extend(self, ext_two: B) -> Ext2 { Ext2 { inner: self.inner, ext_one: self.ext_one, ext_two, } } } impl Ext2 { pub fn new(inner: Inner, ext_one: A, ext_two: B) -> Self { Ext2 { inner, ext_one, ext_two, } } pub fn into_parts(self) -> (Inner, A, B) { (self.inner, self.ext_one, self.ext_two) } pub fn extend(self, ext_three: C) -> Ext3 { Ext3 { inner: self.inner, ext_one: self.ext_one, ext_two: self.ext_two, ext_three, } } } impl Ext3 { pub fn new(inner: Inner, ext_one: A, ext_two: B, ext_three: C) -> Self { Ext3 { inner, ext_one, ext_two, ext_three, } } pub fn into_parts(self) -> (Inner, A, B, C) { (self.inner, self.ext_one, self.ext_two, self.ext_three) } pub fn extend(self, ext_four: D) -> Ext4 { Ext4 { inner: self.inner, ext_one: self.ext_one, ext_two: self.ext_two, ext_three: self.ext_three, ext_four, } } } impl Ext4 { pub fn new(inner: Inner, ext_one: A, ext_two: B, ext_three: C, ext_four: D) -> Self { Ext4 { inner, ext_one, ext_two, ext_three, ext_four, } } pub fn into_parts(self) -> (Inner, A, B, C, D) { ( self.inner, self.ext_one, self.ext_two, self.ext_three, self.ext_four, ) } } impl Extends for Ext1 where Inner: Extends + UnparsedMut, A: UnparsedExtension, Error: From + std::error::Error, { type Error = Error; fn extends(base: Base) -> Result { let mut inner = Inner::extends(base)?; let ext_one = A::try_from_unparsed(&mut inner)?; Ok(Ext1 { inner, ext_one }) } fn retracts(self) -> Result, Self::Error> { let Ext1 { mut inner, ext_one } = self; ext_one.try_into_unparsed(&mut inner)?; inner.retracts() } } impl Extends for Ext2 where Inner: Extends + UnparsedMut, A: UnparsedExtension, B: UnparsedExtension, Error: From + std::error::Error, { type Error = Error; fn extends(base: Base) -> Result { let mut inner = Inner::extends(base)?; let ext_one = A::try_from_unparsed(&mut inner)?; let ext_two = B::try_from_unparsed(&mut inner)?; Ok(Ext2 { inner, ext_one, ext_two, }) } fn retracts(self) -> Result, Self::Error> { let Ext2 { mut inner, ext_one, ext_two, } = self; ext_one.try_into_unparsed(&mut inner)?; ext_two.try_into_unparsed(&mut inner)?; inner.retracts() } } impl Extends for Ext3 where Inner: Extends + UnparsedMut, A: UnparsedExtension, B: UnparsedExtension, C: UnparsedExtension, Error: From + std::error::Error, { type Error = Error; fn extends(base: Base) -> Result { let mut inner = Inner::extends(base)?; let ext_one = A::try_from_unparsed(&mut inner)?; let ext_two = B::try_from_unparsed(&mut inner)?; let ext_three = C::try_from_unparsed(&mut inner)?; Ok(Ext3 { inner, ext_one, ext_two, ext_three, }) } fn retracts(self) -> Result, Self::Error> { let Ext3 { mut inner, ext_one, ext_two, ext_three, } = self; ext_one.try_into_unparsed(&mut inner)?; ext_two.try_into_unparsed(&mut inner)?; ext_three.try_into_unparsed(&mut inner)?; inner.retracts() } } impl Extends for Ext4 where Inner: Extends + UnparsedMut, A: UnparsedExtension, B: UnparsedExtension, C: UnparsedExtension, D: UnparsedExtension, Error: From + std::error::Error, { type Error = Error; fn extends(base: Base) -> Result { let mut inner = Inner::extends(base)?; let ext_one = A::try_from_unparsed(&mut inner)?; let ext_two = B::try_from_unparsed(&mut inner)?; let ext_three = C::try_from_unparsed(&mut inner)?; let ext_four = D::try_from_unparsed(&mut inner)?; Ok(Ext4 { inner, ext_one, ext_two, ext_three, ext_four, }) } fn retracts(self) -> Result, Self::Error> { let Ext4 { mut inner, ext_one, ext_two, ext_three, ext_four, } = self; ext_one.try_into_unparsed(&mut inner)?; ext_two.try_into_unparsed(&mut inner)?; ext_three.try_into_unparsed(&mut inner)?; ext_four.try_into_unparsed(&mut inner)?; inner.retracts() } }