This commit is contained in:
asonix 2020-05-13 22:54:50 -05:00
commit 96e9ad61bf
12 changed files with 2472 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

15
Cargo.toml Normal file
View file

@ -0,0 +1,15 @@
[package]
name = "activitystreams-new"
version = "0.1.0"
authors = ["asonix <asonix@asonix.dog>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
activitystreams = { version = "0.6.1", default-features = false, features = ["kinds","primitives"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[dev-dependencies]
anyhow = "1.0"

36
examples/basic.rs Normal file
View file

@ -0,0 +1,36 @@
use activitystreams_new::{
context,
object::{ApObject, Video},
primitives::{XsdAnyUri, XsdString},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut v: ApObject<Video> = Default::default();
v.inner.context = Some(context().into());
v.inner.id = Some(
"https://example.com/@example/lions"
.parse::<XsdAnyUri>()?
.into(),
);
v.inner.url = Some(
"https://example.com/@example/lions/video.webm"
.parse::<XsdAnyUri>()?
.into(),
);
v.inner.summary = Some(XsdString::from("A cool video").into());
v.inner.media_type = Some("video/webm".parse()?);
v.inner.duration = Some("PT4M20S".parse()?);
println!("Video, {:#?}", v);
let s = serde_json::to_string(&v)?;
println!("json, {}", s);
let v: ApObject<Video> = serde_json::from_str(&s)?;
println!("Video again, {:#?}", v);
Ok(())
}

68
examples/de.rs Normal file
View file

@ -0,0 +1,68 @@
use activitystreams_new::{
collection::OrderedCollection,
object::{ApObject, Page},
traits::Extends,
};
use anyhow::Error;
fn main() -> Result<(), Error> {
let collection_json = r#"{
"type": "OrderedCollection",
"id": "http://lemmy_alpha:8540/federation/c/main",
"context": "https://www.w3.org/ns/activitystreams",
"items": [
{
"type": "Page",
"id": "http://lemmy_alpha:8540/federation/post/2",
"attributedTo": "http://lemmy_alpha:8540/federation/u/2",
"content": "test",
"context": "https://www.w3.org/ns/activitystreams",
"name": "test",
"published": "2020-03-13T00:14:41.188634+00:00"
},
{
"type": "Page",
"id": "http://lemmy_alpha:8540/federation/post/1",
"attributedTo": "http://lemmy_alpha:8540/federation/u/2",
"context": "https://www.w3.org/ns/activitystreams",
"name": "test",
"published": "2020-03-13T00:13:56.311479+00:00"
}
],
"totalItems": 2
}"#;
let page_json = r#"{
"type": "Page",
"id": "http://lemmy_alpha:8540/federation/post/2",
"attributedTo": "http://lemmy_alpha:8540/federation/u/2",
"content": "test",
"name": "test",
"published": "2020-03-13T00:14:41.188634+00:00"
}"#;
let page: ApObject<Page> = serde_json::from_str(page_json)?;
println!("{:#?}", page);
let mut collection: OrderedCollection = serde_json::from_str(collection_json)?;
println!("{:#?}", collection);
let v: Vec<ApObject<Page>> = collection
.items
.clone()
.many()
.into_iter()
.flatten()
.filter_map(|any_object| any_object.object())
.map(|object| object.solidify().and_then(|o| o.extend()))
.collect::<Result<Vec<_>, _>>()?;
println!("{:#?}", v);
let v = v
.into_iter()
.map(|o| o.retracts().and_then(|o| o.into_generic()))
.collect::<Result<Vec<_>, _>>()?;
collection.items.set_many(v);
Ok(())
}

793
src/activity.rs Normal file
View file

@ -0,0 +1,793 @@
use crate::{
object::{AnyObject, Object},
primitives::{OneOrMany, Unparsed},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use std::convert::TryFrom;
pub mod kind {
pub use activitystreams::activity::kind::*;
}
use self::kind::*;
pub type Accept = ActorAndObject<AcceptType>;
pub type Add = ActorAndObject<AddType>;
pub type Block = ActorAndObject<BlockType>;
pub type Create = ActorAndObject<CreateType>;
pub type Dislike = ActorAndObject<DislikeType>;
pub type Flag = ActorAndObject<FlagType>;
pub type Follow = ActorAndObject<FollowType>;
pub type Ignore = ActorAndObject<IgnoreType>;
pub type Join = ActorAndObject<JoinType>;
pub type Leave = ActorAndObject<LeaveType>;
pub type Like = ActorAndObject<LikeType>;
pub type Listen = ActorAndObject<ListenType>;
pub type Read = ActorAndObject<ReadType>;
pub type Reject = ActorAndObject<RejectType>;
pub type TentativeAccept = ActorAndObject<TentativeAcceptType>;
pub type TentativeReject = ActorAndObject<TentativeRejectType>;
pub type Undo = ActorAndObject<UndoType>;
pub type Update = ActorAndObject<UpdateType>;
pub type View = ActorAndObject<ViewType>;
pub type Announce = ActorAndObjectOptTarget<AnnounceType>;
pub type Offer = ActorAndObjectOptTarget<OfferType>;
pub type Move = ActorAndObjectOptOriginAndTarget<MoveType>;
pub type Remove = ActorAndObjectOptOriginAndTarget<RemoveType>;
pub trait NormalActivity {
fn actor(&self) -> &OneOrMany<AnyObject>;
fn object(&self) -> &OneOrMany<AnyObject>;
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instrument: Option<Option<AnyObject>>,
#[serde(flatten)]
pub inner: Object<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ActorAndObject<Kind> {
pub actor: OneOrMany<AnyObject>,
pub object: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Arrive {
pub actor: OneOrMany<AnyObject>,
pub origin: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<ArriveType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Invite {
pub actor: OneOrMany<AnyObject>,
pub object: OneOrMany<AnyObject>,
pub target: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<InviteType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Delete {
pub actor: OneOrMany<AnyObject>,
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<DeleteType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ActorAndObjectOptOriginAndTarget<Kind> {
pub actor: OneOrMany<AnyObject>,
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ActorAndObjectOptTarget<Kind> {
pub actor: OneOrMany<AnyObject>,
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Travel {
pub actor: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<TravelType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Question {
#[serde(skip_serializing_if = "Option::is_none")]
pub one_of: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub any_of: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<QuestionType>,
}
impl<Kind> Activity<Kind> {
fn extending(mut inner: Object<Kind>) -> Result<Self, serde_json::Error> {
let result = inner.remove("result")?;
let instrument = inner.remove("instrument")?;
Ok(Activity {
result,
instrument,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let Activity {
result,
instrument,
mut inner,
} = self;
inner
.insert("result", result)?
.insert("instrument", instrument)?;
Ok(inner)
}
}
impl<Kind> ActorAndObject<Kind> {
fn extending(object: Object<Kind>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let object = inner.remove("object")?;
Ok(ActorAndObject {
actor,
object,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let ActorAndObject {
actor,
object,
mut inner,
} = self;
inner.insert("actor", actor)?.insert("object", object)?;
inner.retracting()
}
}
impl Arrive {
fn extending(object: Object<ArriveType>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let origin = inner.remove("origin")?;
Ok(Arrive {
actor,
origin,
inner,
})
}
fn retracting(self) -> Result<Object<ArriveType>, serde_json::Error> {
let Arrive {
actor,
origin,
mut inner,
} = self;
inner.insert("actor", actor)?.insert("origin", origin)?;
inner.retracting()
}
}
impl Invite {
fn extending(object: Object<InviteType>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let object = inner.remove("object")?;
let target = inner.remove("target")?;
Ok(Invite {
actor,
object,
target,
inner,
})
}
fn retracting(self) -> Result<Object<InviteType>, serde_json::Error> {
let Invite {
actor,
object,
target,
mut inner,
} = self;
inner
.insert("actor", actor)?
.insert("object", object)?
.insert("target", target)?;
inner.retracting()
}
}
impl Delete {
fn extending(object: Object<DeleteType>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let object = inner.remove("object")?;
let origin = inner.remove("origin")?;
Ok(Delete {
actor,
object,
origin,
inner,
})
}
fn retracting(self) -> Result<Object<DeleteType>, serde_json::Error> {
let Delete {
actor,
object,
origin,
mut inner,
} = self;
inner
.insert("actor", actor)?
.insert("object", object)?
.insert("origin", origin)?;
inner.retracting()
}
}
impl<Kind> ActorAndObjectOptOriginAndTarget<Kind> {
fn extending(object: Object<Kind>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let object = inner.remove("object")?;
let origin = inner.remove("origin")?;
let target = inner.remove("target")?;
Ok(ActorAndObjectOptOriginAndTarget {
actor,
object,
origin,
target,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let ActorAndObjectOptOriginAndTarget {
actor,
object,
origin,
target,
mut inner,
} = self;
inner
.insert("actor", actor)?
.insert("object", object)?
.insert("origin", origin)?
.insert("target", target)?;
inner.retracting()
}
}
impl<Kind> ActorAndObjectOptTarget<Kind> {
fn extending(object: Object<Kind>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let object = inner.remove("object")?;
let target = inner.remove("target")?;
Ok(ActorAndObjectOptTarget {
actor,
object,
target,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let ActorAndObjectOptTarget {
actor,
object,
target,
mut inner,
} = self;
inner
.insert("actor", actor)?
.insert("object", object)?
.insert("target", target)?;
inner.retracting()
}
}
impl Travel {
fn extending(object: Object<TravelType>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let actor = inner.remove("actor")?;
let origin = inner.remove("origin")?;
let target = inner.remove("target")?;
Ok(Travel {
actor,
origin,
target,
inner,
})
}
fn retracting(self) -> Result<Object<TravelType>, serde_json::Error> {
let Travel {
actor,
origin,
target,
mut inner,
} = self;
inner
.insert("actor", actor)?
.insert("origin", origin)?
.insert("target", target)?;
inner.retracting()
}
}
impl Question {
fn extending(object: Object<QuestionType>) -> Result<Self, serde_json::Error> {
let mut inner = Activity::extending(object)?;
let one_of = inner.remove("oneOf")?;
let any_of = inner.remove("anyOf")?;
Ok(Question {
one_of,
any_of,
inner,
})
}
fn retracting(self) -> Result<Object<QuestionType>, serde_json::Error> {
let Question {
one_of,
any_of,
mut inner,
} = self;
inner.insert("oneOf", one_of)?.insert("anyOf", any_of)?;
inner.retracting()
}
}
impl<Kind> traits::Base for Activity<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for Activity<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Activity for Activity<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Base for ActorAndObject<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for ActorAndObject<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Activity for ActorAndObject<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Base for ActorAndObjectOptTarget<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for ActorAndObjectOptTarget<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Activity for ActorAndObjectOptTarget<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Base for ActorAndObjectOptOriginAndTarget<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for ActorAndObjectOptOriginAndTarget<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Activity for ActorAndObjectOptOriginAndTarget<Kind> where Kind: std::fmt::Debug {}
impl traits::Base for Arrive {}
impl traits::Object for Arrive {}
impl traits::Activity for Arrive {}
impl traits::IntransitiveActivity for Arrive {}
impl traits::Base for Invite {}
impl traits::Object for Invite {}
impl traits::Activity for Invite {}
impl traits::Base for Delete {}
impl traits::Object for Delete {}
impl traits::Activity for Delete {}
impl traits::Base for Travel {}
impl traits::Object for Travel {}
impl traits::Activity for Travel {}
impl traits::IntransitiveActivity for Travel {}
impl traits::Base for Question {}
impl traits::Object for Question {}
impl traits::Activity for Question {}
impl traits::IntransitiveActivity for Question {}
impl<Kind> Extends<Object<Kind>> for Activity<Kind> {
type Error = serde_json::Error;
fn extends(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<Kind>, Self::Error> {
self.retracting()
}
}
impl<Kind> TryFrom<Object<Kind>> for Activity<Kind> {
type Error = serde_json::Error;
fn try_from(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObject<Kind> {
type Error = serde_json::Error;
fn extends(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<Kind>, Self::Error> {
self.retracting()
}
}
impl<Kind> TryFrom<Object<Kind>> for ActorAndObject<Kind> {
type Error = serde_json::Error;
fn try_from(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<ArriveType>> for Arrive {
type Error = serde_json::Error;
fn extends(object: Object<ArriveType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<ArriveType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<ArriveType>> for Arrive {
type Error = serde_json::Error;
fn try_from(object: Object<ArriveType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<InviteType>> for Invite {
type Error = serde_json::Error;
fn extends(object: Object<InviteType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<InviteType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<InviteType>> for Invite {
type Error = serde_json::Error;
fn try_from(object: Object<InviteType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<DeleteType>> for Delete {
type Error = serde_json::Error;
fn extends(object: Object<DeleteType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<DeleteType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<DeleteType>> for Delete {
type Error = serde_json::Error;
fn try_from(object: Object<DeleteType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObjectOptOriginAndTarget<Kind> {
type Error = serde_json::Error;
fn extends(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<Kind>, Self::Error> {
self.retracting()
}
}
impl<Kind> TryFrom<Object<Kind>> for ActorAndObjectOptOriginAndTarget<Kind> {
type Error = serde_json::Error;
fn try_from(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObjectOptTarget<Kind> {
type Error = serde_json::Error;
fn extends(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<Kind>, Self::Error> {
self.retracting()
}
}
impl<Kind> TryFrom<Object<Kind>> for ActorAndObjectOptTarget<Kind> {
type Error = serde_json::Error;
fn try_from(object: Object<Kind>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<TravelType>> for Travel {
type Error = serde_json::Error;
fn extends(object: Object<TravelType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<TravelType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<TravelType>> for Travel {
type Error = serde_json::Error;
fn try_from(object: Object<TravelType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<QuestionType>> for Question {
type Error = serde_json::Error;
fn extends(object: Object<QuestionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<QuestionType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<QuestionType>> for Question {
type Error = serde_json::Error;
fn try_from(object: Object<QuestionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> WithUnparsed for Activity<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl<Kind> WithUnparsed for ActorAndObject<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Arrive {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Invite {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Delete {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl<Kind> WithUnparsed for ActorAndObjectOptOriginAndTarget<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl<Kind> WithUnparsed for ActorAndObjectOptTarget<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Travel {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Question {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl<Kind> NormalActivity for ActorAndObject<Kind> {
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
fn object(&self) -> &OneOrMany<AnyObject> {
&self.object
}
}
impl<Kind> NormalActivity for ActorAndObjectOptTarget<Kind> {
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
fn object(&self) -> &OneOrMany<AnyObject> {
&self.object
}
}
impl<Kind> NormalActivity for ActorAndObjectOptOriginAndTarget<Kind> {
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
fn object(&self) -> &OneOrMany<AnyObject> {
&self.object
}
}
impl NormalActivity for Invite {
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
fn object(&self) -> &OneOrMany<AnyObject> {
&self.object
}
}
impl NormalActivity for Delete {
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
fn object(&self) -> &OneOrMany<AnyObject> {
&self.object
}
}

162
src/actor.rs Normal file
View file

@ -0,0 +1,162 @@
use crate::{
object::Object,
primitives::{OneOrMany, Unparsed, XsdAnyUri, XsdString},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
pub mod kind {
pub use activitystreams::actor::kind::*;
}
use self::kind::*;
pub type Application = Object<ApplicationType>;
pub type Group = Object<GroupType>;
pub type Organization = Object<OrganizationType>;
pub type Person = Object<PersonType>;
pub type Service = Object<ServiceType>;
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApActor<Inner> {
pub inbox: XsdAnyUri,
pub outbox: XsdAnyUri,
#[serde(skip_serializing_if = "Option::is_none")]
pub following: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub followers: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub liked: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub streams: Option<OneOrMany<XsdAnyUri>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub preferred_username: Option<XsdString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub endpoints: Option<Endpoints>,
#[serde(flatten)]
pub inner: Inner,
}
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Endpoints {
#[serde(skip_serializing_if = "Option::is_none")]
pub proxy_url: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth_authorization_endpoint: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth_token_endpoint: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provide_client_key: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sign_client_key: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shared_inbox: Option<XsdAnyUri>,
}
impl<Inner> ApActor<Inner> {
fn extending(mut inner: Inner) -> Result<Self, serde_json::Error>
where
Inner: WithUnparsed + traits::Actor,
{
let inbox = inner.remove("inbox")?;
let outbox = inner.remove("outbox")?;
let following = inner.remove("following")?;
let followers = inner.remove("followers")?;
let liked = inner.remove("liked")?;
let streams = inner.remove("streams")?;
let preferred_username = inner.remove("preferredUsername")?;
let endpoints = inner.remove("endpoints")?;
Ok(ApActor {
inbox,
outbox,
following,
followers,
liked,
streams,
preferred_username,
endpoints,
inner,
})
}
fn retracting(self) -> Result<Inner, serde_json::Error>
where
Inner: WithUnparsed + traits::Actor,
{
let ApActor {
inbox,
outbox,
following,
followers,
liked,
streams,
preferred_username,
endpoints,
mut inner,
} = self;
inner
.insert("endpoints", endpoints)?
.insert("preferredUsername", preferred_username)?
.insert("streams", streams)?
.insert("liked", liked)?
.insert("followers", followers)?
.insert("following", following)?
.insert("outbox", outbox)?
.insert("inbox", inbox)?;
Ok(inner)
}
}
impl traits::Actor for Application {}
impl traits::Actor for Group {}
impl traits::Actor for Organization {}
impl traits::Actor for Person {}
impl traits::Actor for Service {}
impl<Inner> traits::Base for ApActor<Inner> where Inner: traits::Base {}
impl<Inner> traits::Object for ApActor<Inner> where Inner: traits::Object {}
impl<Inner> traits::Actor for ApActor<Inner> where Inner: traits::Actor {}
impl<Inner> Extends<Inner> for ApActor<Inner>
where
Inner: WithUnparsed + traits::Actor,
{
type Error = serde_json::Error;
fn extends(inner: Inner) -> Result<Self, Self::Error> {
Self::extending(inner)
}
fn retracts(self) -> Result<Inner, Self::Error> {
self.retracting()
}
}
impl<Inner> WithUnparsed for ApActor<Inner>
where
Inner: WithUnparsed,
{
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}

295
src/collection.rs Normal file
View file

@ -0,0 +1,295 @@
use crate::{
object::{AnyObject, Object},
primitives::{OneOrMany, Unparsed},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use activitystreams::primitives::XsdNonNegativeInteger;
use std::convert::TryFrom;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum OrderedCollectionType {
OrderedCollection,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum UnorderedCollectionType {
UnorderedCollection,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum OrderedCollectionPageType {
OrderedCollectionPage,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum UnorderedCollectionPageType {
UnorderedCollectionPage,
}
pub type OrderedCollection = Collection<OrderedCollectionType>;
pub type UnorderedCollection = Collection<UnorderedCollectionType>;
pub type UnorderedCollectionPage = CollectionPage<UnorderedCollectionPageType>;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Collection<Kind> {
pub items: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_items: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current: Option<Object<serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub first: Option<Object<serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last: Option<Object<serde_json::Value>>,
#[serde(flatten)]
pub inner: Object<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CollectionPage<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
pub part_of: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prev: Option<AnyObject>,
#[serde(flatten)]
pub inner: Collection<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderedCollectionPage {
#[serde(skip_serializing_if = "Option::is_none")]
pub start_index: Option<XsdNonNegativeInteger>,
#[serde(flatten)]
pub inner: CollectionPage<OrderedCollectionPageType>,
}
impl<Kind> Collection<Kind> {
fn extending(mut inner: Object<Kind>) -> Result<Self, serde_json::Error> {
let items = inner.remove("items")?;
let total_items = inner.remove("totalItems")?;
let current = inner.remove("current")?;
let first = inner.remove("first")?;
let last = inner.remove("last")?;
Ok(Collection {
items,
total_items,
current,
first,
last,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let Collection {
items,
total_items,
current,
first,
last,
mut inner,
} = self;
inner
.insert("last", last)?
.insert("first", first)?
.insert("current", current)?
.insert("totalItems", total_items)?
.insert("items", items)?;
Ok(inner)
}
}
impl<Kind> CollectionPage<Kind> {
fn extending(object: Object<Kind>) -> Result<Self, serde_json::Error> {
let mut inner = Collection::extending(object)?;
let part_of = inner.remove("partOf")?;
let next = inner.remove("next")?;
let prev = inner.remove("prev")?;
Ok(CollectionPage {
part_of,
next,
prev,
inner,
})
}
fn retracting(self) -> Result<Object<Kind>, serde_json::Error> {
let CollectionPage {
part_of,
next,
prev,
mut inner,
} = self;
inner
.insert("prev", prev)?
.insert("next", next)?
.insert("partOf", part_of)?;
inner.retracting()
}
}
impl OrderedCollectionPage {
fn extending(object: Object<OrderedCollectionPageType>) -> Result<Self, serde_json::Error> {
let mut inner = CollectionPage::extending(object)?;
let start_index = inner.remove("startIndex")?;
Ok(OrderedCollectionPage { start_index, inner })
}
fn retracting(self) -> Result<Object<OrderedCollectionPageType>, serde_json::Error> {
let OrderedCollectionPage {
start_index,
mut inner,
} = self;
inner.insert("startIndex", start_index)?;
inner.retracting()
}
}
impl<Kind> traits::Base for Collection<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for Collection<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Collection for Collection<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Base for CollectionPage<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for CollectionPage<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Collection for CollectionPage<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::CollectionPage for CollectionPage<Kind> where Kind: std::fmt::Debug {}
impl traits::Base for OrderedCollectionPage {}
impl traits::Object for OrderedCollectionPage {}
impl traits::Collection for OrderedCollectionPage {}
impl traits::CollectionPage for OrderedCollectionPage {}
impl Extends<Object<UnorderedCollectionType>> for UnorderedCollection {
type Error = serde_json::Error;
fn extends(object: Object<UnorderedCollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<UnorderedCollectionType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<UnorderedCollectionType>> for UnorderedCollection {
type Error = serde_json::Error;
fn try_from(object: Object<UnorderedCollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<OrderedCollectionType>> for OrderedCollection {
type Error = serde_json::Error;
fn extends(object: Object<OrderedCollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<OrderedCollectionType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<OrderedCollectionType>> for OrderedCollection {
type Error = serde_json::Error;
fn try_from(object: Object<OrderedCollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<UnorderedCollectionPageType>> for UnorderedCollectionPage {
type Error = serde_json::Error;
fn extends(object: Object<UnorderedCollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<UnorderedCollectionPageType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<UnorderedCollectionPageType>> for UnorderedCollectionPage {
type Error = serde_json::Error;
fn try_from(object: Object<UnorderedCollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<OrderedCollectionPageType>> for OrderedCollectionPage {
type Error = serde_json::Error;
fn extends(object: Object<OrderedCollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<OrderedCollectionPageType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<OrderedCollectionPageType>> for OrderedCollectionPage {
type Error = serde_json::Error;
fn try_from(object: Object<OrderedCollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> WithUnparsed for Collection<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl<Kind> WithUnparsed for CollectionPage<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for OrderedCollectionPage {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}

38
src/either.rs Normal file
View file

@ -0,0 +1,38 @@
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(untagged)]
pub enum Either<L, R> {
Left(L),
Right(R),
}
impl<L, R> Either<L, R> {
pub fn left(self) -> Option<L> {
if let Either::Left(l) = self {
Some(l)
} else {
None
}
}
pub fn right(self) -> Option<R> {
if let Either::Right(r) = self {
Some(r)
} else {
None
}
}
pub fn as_ref(&self) -> Either<&L, &R> {
match self {
Either::Left(ref l) => Either::Left(l),
Either::Right(ref r) => Either::Right(r),
}
}
pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
match self {
Either::Left(ref mut l) => Either::Left(l),
Either::Right(ref mut r) => Either::Right(r),
}
}
}

9
src/lib.rs Normal file
View file

@ -0,0 +1,9 @@
pub mod activity;
pub mod actor;
pub mod collection;
pub mod either;
pub mod object;
pub mod primitives;
pub mod traits;
pub use activitystreams::{context, public, security};

806
src/object.rs Normal file
View file

@ -0,0 +1,806 @@
use crate::{
either::Either,
primitives::{
AnyString, MimeMediaType, OneOrMany, Unit, Unparsed, XsdAnyUri, XsdDateTime, XsdDuration,
XsdString,
},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use std::convert::TryFrom;
pub mod kind {
pub use activitystreams::object::kind::*;
}
use self::kind::*;
pub type Article = Object<ArticleType>;
pub type Audio = Object<AudioType>;
pub type Document = Object<DocumentType>;
pub type Event = Object<EventType>;
pub type Image = Object<ImageType>;
pub type Note = Object<NoteType>;
pub type Page = Object<PageType>;
pub type Video = Object<VideoType>;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
struct IdOrObject(Either<XsdAnyUri, Box<Object<serde_json::Value>>>);
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct AnyObject(Either<IdOrObject, XsdString>);
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Object<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<AnyObject>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<Kind>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachment: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attributed_to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub audience: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub media_type: Option<MimeMediaType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub generator: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub image: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_time: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_time: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<XsdDuration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub published: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub in_reply_to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub replies: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bto: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub unparsed: Unparsed,
}
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApObject<Inner> {
#[serde(skip_serializing_if = "Option::is_none")]
pub shares: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub likes: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub upload_media: Option<OneOrMany<XsdAnyUri>>,
#[serde(flatten)]
pub inner: Inner,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Place {
#[serde(skip_serializing_if = "Option::is_none")]
pub accuracy: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub altitude: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub latitude: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub longitude: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub radius: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub units: Option<Unit>,
#[serde(flatten)]
pub inner: Object<PlaceType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Profile {
#[serde(skip_serializing_if = "Option::is_none")]
pub describes: Option<AnyObject>,
#[serde(flatten)]
pub inner: Object<ProfileType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Relationship {
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relationship: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Object<RelationshipType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Tombstone {
#[serde(skip_serializing_if = "Option::is_none")]
pub former_type: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deleted: Option<XsdDateTime>,
#[serde(flatten)]
pub inner: Object<TombstoneType>,
}
impl AnyObject {
pub fn as_xsd_any_uri(&self) -> Option<&XsdAnyUri> {
self.0.as_ref().left().and_then(|l| l.as_xsd_any_uri())
}
pub fn as_xsd_string(&self) -> Option<&XsdString> {
self.0.as_ref().right()
}
pub fn as_object(&self) -> Option<&Object<serde_json::Value>> {
self.0.as_ref().left().and_then(|l| l.as_object())
}
pub fn id(self) -> Option<XsdAnyUri> {
self.0.left().and_then(|l| l.id())
}
pub fn xsd_string(self) -> Option<XsdString> {
self.0.right()
}
pub fn object(self) -> Option<Object<serde_json::Value>> {
self.0.left().and_then(|l| l.object())
}
pub fn set_xsd_any_uri(&mut self, id: XsdAnyUri) {
self.0 = Either::Left(IdOrObject::from_xsd_any_uri(id));
}
pub fn set_object(&mut self, object: Object<serde_json::Value>) {
self.0 = Either::Left(IdOrObject::from_object(object));
}
pub fn set_xsd_string(&mut self, xsd_string: XsdString) {
self.0 = Either::Right(xsd_string);
}
pub fn from_xsd_any_uri(id: XsdAnyUri) -> Self {
AnyObject(Either::Left(IdOrObject::from_xsd_any_uri(id)))
}
pub fn from_object(object: Object<serde_json::Value>) -> Self {
AnyObject(Either::Left(IdOrObject::from_object(object)))
}
pub fn from_xsd_string(xsd_string: XsdString) -> Self {
AnyObject(Either::Right(xsd_string))
}
}
impl IdOrObject {
fn as_xsd_any_uri(&self) -> Option<&XsdAnyUri> {
self.0.as_ref().left()
}
fn as_object(&self) -> Option<&Object<serde_json::Value>> {
self.0.as_ref().right().map(|b| b.as_ref())
}
fn id(self) -> Option<XsdAnyUri> {
self.0.left()
}
fn object(self) -> Option<Object<serde_json::Value>> {
self.0.right().map(|b| *b)
}
fn from_xsd_any_uri(id: XsdAnyUri) -> Self {
IdOrObject(Either::Left(id))
}
fn from_object(object: Object<serde_json::Value>) -> Self {
IdOrObject(Either::Right(Box::new(object)))
}
}
impl OneOrMany<AnyObject> {
pub fn as_single_xsd_any_uri(&self) -> Option<&XsdAnyUri> {
self.as_one().and_then(|inner| inner.as_xsd_any_uri())
}
pub fn as_single_xsd_string(&self) -> Option<&XsdString> {
self.as_one().and_then(|inner| inner.as_xsd_string())
}
pub fn as_single_object(&self) -> Option<&Object<serde_json::Value>> {
self.as_one().and_then(|inner| inner.as_object())
}
pub fn single_xsd_any_uri(self) -> Option<XsdAnyUri> {
self.one().and_then(|inner| inner.id())
}
pub fn single_xsd_string(self) -> Option<XsdString> {
self.one().and_then(|inner| inner.xsd_string())
}
pub fn single_object(self) -> Option<Object<serde_json::Value>> {
self.one().and_then(|inner| inner.object())
}
pub fn from_xsd_any_uri(id: XsdAnyUri) -> Self {
OneOrMany(Either::Left(AnyObject::from_xsd_any_uri(id)))
}
pub fn from_xsd_string(xsd_string: XsdString) -> Self {
OneOrMany(Either::Left(AnyObject::from_xsd_string(xsd_string)))
}
pub fn from_object(object: Object<serde_json::Value>) -> Self {
OneOrMany(Either::Left(AnyObject::from_object(object)))
}
pub fn set_single_xsd_any_uri(&mut self, id: XsdAnyUri) -> &mut Self {
self.0 = Either::Left(AnyObject::from_xsd_any_uri(id));
self
}
pub fn set_single_xsd_string(&mut self, xsd_string: XsdString) -> &mut Self {
self.0 = Either::Left(AnyObject::from_xsd_string(xsd_string));
self
}
pub fn set_single_object(&mut self, object: Object<serde_json::Value>) -> &mut Self {
self.0 = Either::Left(AnyObject::from_object(object));
self
}
pub fn add_xsd_any_uri(&mut self, id: XsdAnyUri) -> &mut Self {
self.add(AnyObject::from_xsd_any_uri(id))
}
pub fn add_xsd_string(&mut self, xsd_string: XsdString) -> &mut Self {
self.add(AnyObject::from_xsd_string(xsd_string))
}
pub fn add_object(&mut self, object: Object<serde_json::Value>) -> &mut Self {
self.add(AnyObject::from_object(object))
}
}
impl Object<serde_json::Value> {
pub fn solidify<Kind>(self) -> Result<Object<Kind>, serde_json::Error>
where
Kind: serde::de::DeserializeOwned,
{
self.try_map_kind(serde_json::from_value)
}
}
impl<Kind> Object<Kind> {
pub fn into_generic(self) -> Result<Object<serde_json::Value>, serde_json::Error>
where
Kind: serde::ser::Serialize,
{
self.try_map_kind(serde_json::to_value)
}
pub fn map_kind<NewKind>(self, f: impl Fn(Kind) -> NewKind) -> Object<NewKind> {
Object {
kind: self.kind.map(f),
context: self.context,
id: self.id,
attachment: self.attachment,
attributed_to: self.attributed_to,
audience: self.audience,
content: self.content,
name: self.name,
summary: self.summary,
url: self.url,
media_type: self.media_type,
generator: self.generator,
image: self.image,
location: self.location,
preview: self.preview,
start_time: self.start_time,
end_time: self.end_time,
duration: self.duration,
published: self.published,
updated: self.updated,
in_reply_to: self.in_reply_to,
replies: self.replies,
to: self.to,
bto: self.bto,
cc: self.cc,
bcc: self.bcc,
unparsed: self.unparsed,
}
}
pub fn try_map_kind<NewKind, E>(
self,
f: impl Fn(Kind) -> Result<NewKind, E>,
) -> Result<Object<NewKind>, E> {
Ok(Object {
kind: if let Some(kind) = self.kind {
Some((f)(kind)?)
} else {
None
},
context: self.context,
id: self.id,
attachment: self.attachment,
attributed_to: self.attributed_to,
audience: self.audience,
content: self.content,
name: self.name,
summary: self.summary,
url: self.url,
media_type: self.media_type,
generator: self.generator,
image: self.image,
location: self.location,
preview: self.preview,
start_time: self.start_time,
end_time: self.end_time,
duration: self.duration,
published: self.published,
updated: self.updated,
in_reply_to: self.in_reply_to,
replies: self.replies,
to: self.to,
bto: self.bto,
cc: self.cc,
bcc: self.bcc,
unparsed: self.unparsed,
})
}
pub fn extend<Extended>(self) -> Result<Extended, Extended::Error>
where
Extended: Extends<Self>,
{
Extended::extends(self)
}
}
impl<Inner> ApObject<Inner> {
fn extending(mut inner: Inner) -> Result<Self, serde_json::Error>
where
Inner: WithUnparsed + traits::Object,
{
let shares = inner.remove("shares")?;
let likes = inner.remove("likes")?;
let source = inner.remove("source")?;
let upload_media = inner.remove("uploadMedia")?;
Ok(ApObject {
shares,
likes,
source,
upload_media,
inner,
})
}
fn retracting(self) -> Result<Inner, serde_json::Error>
where
Inner: WithUnparsed + traits::Object,
{
let ApObject {
shares,
likes,
source,
upload_media,
mut inner,
} = self;
inner
.insert("uploadMedia", upload_media)?
.insert("source", source)?
.insert("likes", likes)?
.insert("shares", shares)?;
Ok(inner)
}
}
impl Place {
fn extending(mut inner: Object<PlaceType>) -> Result<Self, serde_json::Error> {
let accuracy = inner.remove("accuracy")?;
let altitude = inner.remove("altitude")?;
let latitude = inner.remove("latitude")?;
let longitude = inner.remove("longitude")?;
let radius = inner.remove("radius")?;
let units = inner.remove("units")?;
Ok(Place {
accuracy,
altitude,
latitude,
longitude,
radius,
units,
inner,
})
}
fn retracting(self) -> Result<Object<PlaceType>, serde_json::Error> {
let Place {
accuracy,
altitude,
latitude,
longitude,
radius,
units,
mut inner,
} = self;
inner
.insert("units", units)?
.insert("radius", radius)?
.insert("longitude", longitude)?
.insert("latitude", latitude)?
.insert("altitude", altitude)?
.insert("accuracy", accuracy)?;
Ok(inner)
}
}
impl Profile {
fn extending(mut inner: Object<ProfileType>) -> Result<Self, serde_json::Error> {
let describes = inner.remove("describes")?;
Ok(Profile { describes, inner })
}
fn retracting(self) -> Result<Object<ProfileType>, serde_json::Error> {
let Profile {
describes,
mut inner,
} = self;
inner.insert("describes", describes)?;
Ok(inner)
}
}
impl Relationship {
fn extending(mut inner: Object<RelationshipType>) -> Result<Self, serde_json::Error> {
let subject = inner.remove("subject")?;
let object = inner.remove("object")?;
let relationship = inner.remove("relationship")?;
Ok(Relationship {
subject,
object,
relationship,
inner,
})
}
fn retracting(self) -> Result<Object<RelationshipType>, serde_json::Error> {
let Relationship {
subject,
object,
relationship,
mut inner,
} = self;
inner
.insert("subject", subject)?
.insert("object", object)?
.insert("relationship", relationship)?;
Ok(inner)
}
}
impl Tombstone {
fn extending(mut inner: Object<TombstoneType>) -> Result<Self, serde_json::Error> {
let former_type = inner.remove("formerType")?;
let deleted = inner.remove("deleted")?;
Ok(Tombstone {
former_type,
deleted,
inner,
})
}
fn retracting(self) -> Result<Object<TombstoneType>, serde_json::Error> {
let Tombstone {
former_type,
deleted,
mut inner,
} = self;
inner
.insert("formerType", former_type)?
.insert("deleted", deleted)?;
Ok(inner)
}
}
impl<Kind> traits::Base for Object<Kind> where Kind: std::fmt::Debug {}
impl<Kind> traits::Object for Object<Kind> where Kind: std::fmt::Debug {}
impl<Inner> traits::Base for ApObject<Inner> where Inner: traits::Base {}
impl<Inner> traits::Object for ApObject<Inner> where Inner: traits::Object {}
impl traits::Base for Place {}
impl traits::Object for Place {}
impl traits::Base for Profile {}
impl traits::Object for Profile {}
impl traits::Base for Relationship {}
impl traits::Object for Relationship {}
impl traits::Base for Tombstone {}
impl traits::Object for Tombstone {}
impl<Inner> Extends<Inner> for ApObject<Inner>
where
Inner: WithUnparsed + traits::Object,
{
type Error = serde_json::Error;
fn extends(inner: Inner) -> Result<Self, Self::Error> {
Self::extending(inner)
}
fn retracts(self) -> Result<Inner, Self::Error> {
self.retracting()
}
}
impl Extends<Object<PlaceType>> for Place {
type Error = serde_json::Error;
fn extends(object: Object<PlaceType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<PlaceType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<PlaceType>> for Place {
type Error = serde_json::Error;
fn try_from(object: Object<PlaceType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<ProfileType>> for Profile {
type Error = serde_json::Error;
fn extends(object: Object<ProfileType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<ProfileType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<ProfileType>> for Profile {
type Error = serde_json::Error;
fn try_from(object: Object<ProfileType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<RelationshipType>> for Relationship {
type Error = serde_json::Error;
fn extends(object: Object<RelationshipType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<RelationshipType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<RelationshipType>> for Relationship {
type Error = serde_json::Error;
fn try_from(object: Object<RelationshipType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl Extends<Object<TombstoneType>> for Tombstone {
type Error = serde_json::Error;
fn extends(object: Object<TombstoneType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<TombstoneType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<TombstoneType>> for Tombstone {
type Error = serde_json::Error;
fn try_from(object: Object<TombstoneType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl<Kind> WithUnparsed for Object<Kind> {
fn unparsed(&self) -> &Unparsed {
&self.unparsed
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
&mut self.unparsed
}
}
impl<Inner> WithUnparsed for ApObject<Inner>
where
Inner: WithUnparsed,
{
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Place {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Profile {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Relationship {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl WithUnparsed for Tombstone {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self.inner.unparsed_mut()
}
}
impl From<Object<serde_json::Value>> for AnyObject {
fn from(o: Object<serde_json::Value>) -> Self {
Self::from_object(o)
}
}
impl From<XsdAnyUri> for AnyObject {
fn from(id: XsdAnyUri) -> Self {
Self::from_xsd_any_uri(id)
}
}
impl From<XsdString> for AnyObject {
fn from(xsd_string: XsdString) -> Self {
Self::from_xsd_string(xsd_string)
}
}
impl From<Object<serde_json::Value>> for OneOrMany<AnyObject> {
fn from(object: Object<serde_json::Value>) -> Self {
Self::from_object(object)
}
}
impl From<XsdAnyUri> for OneOrMany<AnyObject> {
fn from(xsd_any_uri: XsdAnyUri) -> Self {
Self::from_xsd_any_uri(xsd_any_uri)
}
}
impl From<XsdString> for OneOrMany<AnyObject> {
fn from(xsd_string: XsdString) -> Self {
Self::from_xsd_string(xsd_string)
}
}

210
src/primitives.rs Normal file
View file

@ -0,0 +1,210 @@
use crate::either::Either;
pub use activitystreams::primitives::{
Length, MimeMediaType, RdfLangString, XsdAnyUri, XsdDateTime, XsdDuration,
XsdNonNegativeInteger, XsdString,
};
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct Unparsed(std::collections::HashMap<String, serde_json::Value>);
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct AnyString(Either<XsdString, RdfLangString>);
pub type Unit = Either<Length, XsdString>;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct OneOrMany<T>(pub Either<T, Vec<T>>);
impl Unparsed {
pub(crate) fn remove(&mut self, key: &str) -> serde_json::Value {
self.0.remove(key).unwrap_or(serde_json::Value::Null)
}
pub(crate) fn insert(&mut self, key: String, value: serde_json::Value) {
self.0.insert(key, value);
}
}
impl AnyString {
pub fn as_xsd_string(&self) -> Option<&XsdString> {
self.0.as_ref().left()
}
pub fn as_rdf_lang_string(&self) -> Option<&RdfLangString> {
self.0.as_ref().right()
}
pub fn xsd_string(self) -> Option<XsdString> {
self.0.left()
}
pub fn rdf_lang_string(self) -> Option<RdfLangString> {
self.0.right()
}
pub fn from_xsd_string<T>(string: T) -> Self
where
XsdString: From<T>,
{
AnyString(Either::Left(string.into()))
}
pub fn from_rdf_lang_string<T>(string: T) -> Self
where
RdfLangString: From<T>,
{
AnyString(Either::Right(string.into()))
}
pub fn set_xsd_string<T>(&mut self, string: T)
where
XsdString: From<T>,
{
self.0 = Either::Left(string.into());
}
pub fn set_rdf_lang_string<T>(&mut self, string: T)
where
RdfLangString: From<T>,
{
self.0 = Either::Right(string.into());
}
}
impl OneOrMany<AnyString> {
pub fn as_single_xsd_string(&self) -> Option<&XsdString> {
self.as_one()
.and_then(|any_string| any_string.as_xsd_string())
}
pub fn as_single_rdf_lang_string(&self) -> Option<&RdfLangString> {
self.as_one()
.and_then(|any_string| any_string.as_rdf_lang_string())
}
pub fn single_xsd_string(self) -> Option<XsdString> {
self.one().and_then(|any_string| any_string.xsd_string())
}
pub fn single_rdf_lang_string(self) -> Option<RdfLangString> {
self.one()
.and_then(|any_string| any_string.rdf_lang_string())
}
pub fn from_xsd_string<T>(string: T) -> Self
where
XsdString: From<T>,
{
Self::from_one(AnyString::from_xsd_string(string))
}
pub fn from_rdf_lang_string<T>(string: T) -> Self
where
RdfLangString: From<T>,
{
Self::from_one(AnyString::from_rdf_lang_string(string))
}
}
impl<T> OneOrMany<T> {
pub fn as_one(&self) -> Option<&T> {
self.0.as_ref().left()
}
pub fn one(self) -> Option<T> {
self.0.left()
}
pub fn as_many(&self) -> Option<&[T]> {
self.0.as_ref().right().map(|v| v.as_ref())
}
pub fn many(self) -> Option<Vec<T>> {
self.0.right()
}
pub fn unwrap_to_vec(self) -> Vec<T> {
match self.0 {
Either::Left(t) => vec![t],
Either::Right(v) => v,
}
}
pub fn from_one(t: T) -> Self {
OneOrMany(Either::Left(t))
}
pub fn from_many(items: Vec<T>) -> Self {
OneOrMany(Either::Right(items))
}
pub fn set_one<U>(&mut self, u: U) -> &mut Self
where
T: From<U>,
{
self.0 = Either::Left(u.into());
self
}
pub fn set_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
where
T: From<U>,
{
self.0 = Either::Right(items.into_iter().map(T::from).collect());
self
}
pub fn add<U>(&mut self, u: U) -> &mut Self
where
T: From<U>,
{
let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) {
Either::Left(one) => vec![one],
Either::Right(v) => v,
};
v.push(u.into());
self.0 = Either::Right(v);
self
}
pub fn add_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
where
T: From<U>,
{
let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) {
Either::Left(one) => vec![one],
Either::Right(v) => v,
};
v.extend(items.into_iter().map(T::from));
self.0 = Either::Right(v);
self
}
}
impl From<XsdString> for AnyString {
fn from(s: XsdString) -> Self {
AnyString::from_xsd_string(s)
}
}
impl From<RdfLangString> for AnyString {
fn from(s: RdfLangString) -> Self {
AnyString::from_rdf_lang_string(s)
}
}
impl From<XsdString> for OneOrMany<AnyString> {
fn from(s: XsdString) -> Self {
OneOrMany::<AnyString>::from_xsd_string(s)
}
}
impl From<RdfLangString> for OneOrMany<AnyString> {
fn from(s: RdfLangString) -> Self {
OneOrMany::<AnyString>::from_rdf_lang_string(s)
}
}

38
src/traits.rs Normal file
View file

@ -0,0 +1,38 @@
use crate::primitives::Unparsed;
pub use activitystreams::{
Activity, Actor, Base, Collection, CollectionPage, IntransitiveActivity, Link, Object,
};
pub trait WithUnparsed {
fn unparsed(&self) -> &Unparsed;
fn unparsed_mut(&mut self) -> &mut Unparsed;
}
pub trait WithUnparsedExt: WithUnparsed {
fn remove<T>(&mut self, key: &str) -> Result<T, serde_json::Error>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_value(self.unparsed_mut().remove(key))
}
fn insert<T>(&mut self, key: &str, value: T) -> Result<&mut Self, serde_json::Error>
where
T: serde::ser::Serialize,
{
self.unparsed_mut()
.insert(key.to_owned(), serde_json::to_value(value)?);
Ok(self)
}
}
pub trait Extends<T>: Sized {
type Error: std::error::Error;
fn extends(t: T) -> Result<Self, Self::Error>;
fn retracts(self) -> Result<T, Self::Error>;
}
impl<T> WithUnparsedExt for T where T: WithUnparsed {}