Hmmm...
This commit is contained in:
commit
96e9ad61bf
12 changed files with 2472 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
15
Cargo.toml
Normal file
15
Cargo.toml
Normal 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
36
examples/basic.rs
Normal 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
68
examples/de.rs
Normal 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
793
src/activity.rs
Normal 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
162
src/actor.rs
Normal 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
295
src/collection.rs
Normal 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
38
src/either.rs
Normal 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
9
src/lib.rs
Normal 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
806
src/object.rs
Normal 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
210
src/primitives.rs
Normal 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
38
src/traits.rs
Normal 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 {}
|
Loading…
Reference in a new issue