Add builder

This commit is contained in:
asonix 2020-05-14 11:23:38 -05:00
parent 96e9ad61bf
commit 4cb98a6706
7 changed files with 476 additions and 82 deletions

View file

@ -10,6 +10,10 @@ edition = "2018"
activitystreams = { version = "0.6.1", default-features = false, features = ["kinds","primitives"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
typed-builder = "0.5.1"
[dev-dependencies]
anyhow = "1.0"
[patch.crates-io]
typed-builder = { git = "https://git.asonix.dog/asonix/typed-builder" }

View file

@ -5,22 +5,16 @@ use activitystreams_new::{
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut v: ApObject<Video> = Default::default();
let video = Video::builder()
.context(context())
.id("https://example.com/@example/lions".parse::<XsdAnyUri>()?)
.url("https://example.com/@example/lions/video.webm".parse::<XsdAnyUri>()?)
.summary(XsdString::from("A cool video"))
.media_type("video/webm".parse()?)
.duration("PT4M20S".parse()?)
.build();
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()?);
let v = ApObject::builder().inner(video).build();
println!("Video, {:#?}", v);

View file

@ -4,6 +4,7 @@ use crate::{
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use std::convert::TryFrom;
use typed_builder::TypedBuilder;
pub mod kind {
pub use activitystreams::activity::kind::*;
@ -37,119 +38,159 @@ pub type Offer = ActorAndObjectOptTarget<OfferType>;
pub type Move = ActorAndObjectOptOriginAndTarget<MoveType>;
pub type Remove = ActorAndObjectOptOriginAndTarget<RemoveType>;
pub trait NormalActivity {
pub trait NormalActivity: traits::Activity {
fn actor(&self) -> &OneOrMany<AnyObject>;
fn object(&self) -> &OneOrMany<AnyObject>;
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Activity<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub result: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instrument: Option<Option<AnyObject>>,
#[builder(default, setter(strip_option, into))]
pub instrument: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Object<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct ActorAndObject<Kind> {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub object: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Arrive {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub origin: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<ArriveType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Invite {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub object: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub target: OneOrMany<AnyObject>,
#[serde(flatten)]
pub inner: Activity<InviteType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Delete {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<DeleteType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct ActorAndObjectOptOriginAndTarget<Kind> {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct ActorAndObjectOptTarget<Kind> {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[builder(setter(into))]
pub object: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Travel {
#[builder(setter(into))]
pub actor: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub origin: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub target: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Activity<TravelType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Question {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub one_of: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub any_of: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
@ -492,6 +533,14 @@ impl<Kind> TryFrom<Object<Kind>> for Activity<Kind> {
}
}
impl<Kind> TryFrom<Activity<Kind>> for Object<Kind> {
type Error = serde_json::Error;
fn try_from(activity: Activity<Kind>) -> Result<Self, Self::Error> {
activity.retracting()
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObject<Kind> {
type Error = serde_json::Error;
@ -512,6 +561,14 @@ impl<Kind> TryFrom<Object<Kind>> for ActorAndObject<Kind> {
}
}
impl<Kind> TryFrom<ActorAndObject<Kind>> for Object<Kind> {
type Error = serde_json::Error;
fn try_from(activity: ActorAndObject<Kind>) -> Result<Self, Self::Error> {
activity.retracting()
}
}
impl Extends<Object<ArriveType>> for Arrive {
type Error = serde_json::Error;
@ -532,6 +589,14 @@ impl TryFrom<Object<ArriveType>> for Arrive {
}
}
impl TryFrom<Arrive> for Object<ArriveType> {
type Error = serde_json::Error;
fn try_from(arrive: Arrive) -> Result<Self, Self::Error> {
arrive.retracting()
}
}
impl Extends<Object<InviteType>> for Invite {
type Error = serde_json::Error;
@ -552,6 +617,14 @@ impl TryFrom<Object<InviteType>> for Invite {
}
}
impl TryFrom<Invite> for Object<InviteType> {
type Error = serde_json::Error;
fn try_from(invite: Invite) -> Result<Self, Self::Error> {
invite.retracting()
}
}
impl Extends<Object<DeleteType>> for Delete {
type Error = serde_json::Error;
@ -572,6 +645,14 @@ impl TryFrom<Object<DeleteType>> for Delete {
}
}
impl TryFrom<Delete> for Object<DeleteType> {
type Error = serde_json::Error;
fn try_from(delete: Delete) -> Result<Self, Self::Error> {
delete.retracting()
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObjectOptOriginAndTarget<Kind> {
type Error = serde_json::Error;
@ -592,6 +673,14 @@ impl<Kind> TryFrom<Object<Kind>> for ActorAndObjectOptOriginAndTarget<Kind> {
}
}
impl<Kind> TryFrom<ActorAndObjectOptOriginAndTarget<Kind>> for Object<Kind> {
type Error = serde_json::Error;
fn try_from(activity: ActorAndObjectOptOriginAndTarget<Kind>) -> Result<Self, Self::Error> {
activity.retracting()
}
}
impl<Kind> Extends<Object<Kind>> for ActorAndObjectOptTarget<Kind> {
type Error = serde_json::Error;
@ -612,6 +701,14 @@ impl<Kind> TryFrom<Object<Kind>> for ActorAndObjectOptTarget<Kind> {
}
}
impl<Kind> TryFrom<ActorAndObjectOptTarget<Kind>> for Object<Kind> {
type Error = serde_json::Error;
fn try_from(activity: ActorAndObjectOptTarget<Kind>) -> Result<Self, Self::Error> {
activity.retracting()
}
}
impl Extends<Object<TravelType>> for Travel {
type Error = serde_json::Error;
@ -632,6 +729,14 @@ impl TryFrom<Object<TravelType>> for Travel {
}
}
impl TryFrom<Travel> for Object<TravelType> {
type Error = serde_json::Error;
fn try_from(travel: Travel) -> Result<Self, Self::Error> {
travel.retracting()
}
}
impl Extends<Object<QuestionType>> for Question {
type Error = serde_json::Error;
@ -652,6 +757,14 @@ impl TryFrom<Object<QuestionType>> for Question {
}
}
impl TryFrom<Question> for Object<QuestionType> {
type Error = serde_json::Error;
fn try_from(question: Question) -> Result<Self, Self::Error> {
question.retracting()
}
}
impl<Kind> WithUnparsed for Activity<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()
@ -742,7 +855,10 @@ impl WithUnparsed for Question {
}
}
impl<Kind> NormalActivity for ActorAndObject<Kind> {
impl<Kind> NormalActivity for ActorAndObject<Kind>
where
Kind: std::fmt::Debug,
{
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
@ -752,7 +868,10 @@ impl<Kind> NormalActivity for ActorAndObject<Kind> {
}
}
impl<Kind> NormalActivity for ActorAndObjectOptTarget<Kind> {
impl<Kind> NormalActivity for ActorAndObjectOptTarget<Kind>
where
Kind: std::fmt::Debug,
{
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}
@ -762,7 +881,10 @@ impl<Kind> NormalActivity for ActorAndObjectOptTarget<Kind> {
}
}
impl<Kind> NormalActivity for ActorAndObjectOptOriginAndTarget<Kind> {
impl<Kind> NormalActivity for ActorAndObjectOptOriginAndTarget<Kind>
where
Kind: std::fmt::Debug,
{
fn actor(&self) -> &OneOrMany<AnyObject> {
&self.actor
}

View file

@ -3,6 +3,7 @@ use crate::{
primitives::{OneOrMany, Unparsed, XsdAnyUri, XsdString},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use typed_builder::TypedBuilder;
pub mod kind {
pub use activitystreams::actor::kind::*;
@ -16,53 +17,66 @@ pub type Organization = Object<OrganizationType>;
pub type Person = Object<PersonType>;
pub type Service = Object<ServiceType>;
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct ApActor<Inner> {
pub inbox: XsdAnyUri,
pub outbox: XsdAnyUri,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub following: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub followers: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub liked: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub streams: Option<OneOrMany<XsdAnyUri>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub preferred_username: Option<XsdString>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub endpoints: Option<Endpoints>,
#[serde(flatten)]
pub inner: Inner,
}
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
pub struct Endpoints {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub proxy_url: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub oauth_authorization_endpoint: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub oauth_token_endpoint: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub provide_client_key: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub sign_client_key: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub shared_inbox: Option<XsdAnyUri>,
}

View file

@ -1,76 +1,74 @@
use crate::{
object::{AnyObject, Object},
primitives::{OneOrMany, Unparsed},
primitives::{OneOrMany, Unparsed, XsdNonNegativeInteger},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use activitystreams::primitives::XsdNonNegativeInteger;
use std::convert::TryFrom;
use typed_builder::TypedBuilder;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum OrderedCollectionType {
OrderedCollection,
pub mod kind {
pub use activitystreams::collection::kind::*;
}
#[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,
}
use self::kind::*;
pub type OrderedCollection = Collection<OrderedCollectionType>;
pub type UnorderedCollection = Collection<UnorderedCollectionType>;
pub type UnorderedCollectionPage = CollectionPage<UnorderedCollectionPageType>;
pub type UnorderedCollection = Collection<CollectionType>;
pub type UnorderedCollectionPage = CollectionPage<CollectionPageType>;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Collection<Kind> {
#[builder(setter(into))]
pub items: OneOrMany<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_items: Option<i64>,
#[builder(default, setter(strip_option, into))]
pub total_items: Option<XsdNonNegativeInteger>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current: Option<Object<serde_json::Value>>,
#[builder(default, setter(strip_option, into))]
pub current: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub first: Option<Object<serde_json::Value>>,
#[builder(default, setter(strip_option, into))]
pub first: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last: Option<Object<serde_json::Value>>,
#[builder(default, setter(strip_option, into))]
pub last: Option<AnyObject>,
#[serde(flatten)]
pub inner: Object<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct CollectionPage<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub part_of: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub next: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub prev: Option<AnyObject>,
#[serde(flatten)]
pub inner: Collection<Kind>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct OrderedCollectionPage {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub start_index: Option<XsdNonNegativeInteger>,
#[serde(flatten)]
@ -184,26 +182,34 @@ impl traits::Object for OrderedCollectionPage {}
impl traits::Collection for OrderedCollectionPage {}
impl traits::CollectionPage for OrderedCollectionPage {}
impl Extends<Object<UnorderedCollectionType>> for UnorderedCollection {
impl Extends<Object<CollectionType>> for UnorderedCollection {
type Error = serde_json::Error;
fn extends(object: Object<UnorderedCollectionType>) -> Result<Self, Self::Error> {
fn extends(object: Object<CollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<UnorderedCollectionType>, Self::Error> {
fn retracts(self) -> Result<Object<CollectionType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<UnorderedCollectionType>> for UnorderedCollection {
impl TryFrom<Object<CollectionType>> for UnorderedCollection {
type Error = serde_json::Error;
fn try_from(object: Object<UnorderedCollectionType>) -> Result<Self, Self::Error> {
fn try_from(object: Object<CollectionType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl TryFrom<UnorderedCollection> for Object<CollectionType> {
type Error = serde_json::Error;
fn try_from(collection: UnorderedCollection) -> Result<Self, Self::Error> {
collection.retracting()
}
}
impl Extends<Object<OrderedCollectionType>> for OrderedCollection {
type Error = serde_json::Error;
@ -224,26 +230,42 @@ impl TryFrom<Object<OrderedCollectionType>> for OrderedCollection {
}
}
impl Extends<Object<UnorderedCollectionPageType>> for UnorderedCollectionPage {
impl TryFrom<OrderedCollection> for Object<OrderedCollectionType> {
type Error = serde_json::Error;
fn extends(object: Object<UnorderedCollectionPageType>) -> Result<Self, Self::Error> {
fn try_from(collection: OrderedCollection) -> Result<Self, Self::Error> {
collection.retracting()
}
}
impl Extends<Object<CollectionPageType>> for UnorderedCollectionPage {
type Error = serde_json::Error;
fn extends(object: Object<CollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
fn retracts(self) -> Result<Object<UnorderedCollectionPageType>, Self::Error> {
fn retracts(self) -> Result<Object<CollectionPageType>, Self::Error> {
self.retracting()
}
}
impl TryFrom<Object<UnorderedCollectionPageType>> for UnorderedCollectionPage {
impl TryFrom<Object<CollectionPageType>> for UnorderedCollectionPage {
type Error = serde_json::Error;
fn try_from(object: Object<UnorderedCollectionPageType>) -> Result<Self, Self::Error> {
fn try_from(object: Object<CollectionPageType>) -> Result<Self, Self::Error> {
Self::extending(object)
}
}
impl TryFrom<UnorderedCollectionPage> for Object<CollectionPageType> {
type Error = serde_json::Error;
fn try_from(collection_page: UnorderedCollectionPage) -> Result<Self, Self::Error> {
collection_page.retracting()
}
}
impl Extends<Object<OrderedCollectionPageType>> for OrderedCollectionPage {
type Error = serde_json::Error;
@ -264,6 +286,14 @@ impl TryFrom<Object<OrderedCollectionPageType>> for OrderedCollectionPage {
}
}
impl TryFrom<OrderedCollectionPage> for Object<OrderedCollectionPageType> {
type Error = serde_json::Error;
fn try_from(collection_page: OrderedCollectionPage) -> Result<Self, Self::Error> {
collection_page.retracting()
}
}
impl<Kind> WithUnparsed for Collection<Kind> {
fn unparsed(&self) -> &Unparsed {
self.inner.unparsed()

View file

@ -2,11 +2,12 @@ use crate::{
either::Either,
primitives::{
AnyString, MimeMediaType, OneOrMany, Unit, Unparsed, XsdAnyUri, XsdDateTime, XsdDuration,
XsdString,
XsdFloat, XsdString,
},
traits::{self, Extends, WithUnparsed, WithUnparsedExt},
};
use std::convert::TryFrom;
use typed_builder::TypedBuilder;
pub mod kind {
pub use activitystreams::object::kind::*;
@ -31,165 +32,214 @@ struct IdOrObject(Either<XsdAnyUri, Box<Object<serde_json::Value>>>);
#[serde(transparent)]
pub struct AnyObject(Either<IdOrObject, XsdString>);
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Object<Kind> {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub context: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub id: Option<AnyObject>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub kind: Option<Kind>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub attachment: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub attributed_to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub audience: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub content: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub name: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub summary: Option<OneOrMany<AnyString>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub url: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub media_type: Option<MimeMediaType>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub generator: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub image: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub location: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub preview: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub start_time: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub end_time: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub duration: Option<XsdDuration>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub published: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub updated: Option<XsdDateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub in_reply_to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub replies: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub to: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub bto: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub cc: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub bcc: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
#[builder(default)]
pub unparsed: Unparsed,
}
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct ApObject<Inner> {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub shares: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub likes: Option<XsdAnyUri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub source: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub upload_media: Option<OneOrMany<XsdAnyUri>>,
#[serde(flatten)]
pub inner: Inner,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[builder(doc)]
pub struct Place {
#[serde(skip_serializing_if = "Option::is_none")]
pub accuracy: Option<f64>,
#[builder(default, setter(strip_option, into))]
pub accuracy: Option<XsdFloat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub altitude: Option<f64>,
#[builder(default, setter(strip_option, into))]
pub altitude: Option<XsdFloat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub latitude: Option<f64>,
#[builder(default, setter(strip_option, into))]
pub latitude: Option<XsdFloat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub longitude: Option<f64>,
#[builder(default, setter(strip_option, into))]
pub longitude: Option<XsdFloat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub radius: Option<f64>,
#[builder(default, setter(strip_option, into))]
pub radius: Option<XsdFloat>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub units: Option<Unit>,
#[serde(flatten)]
pub inner: Object<PlaceType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[builder(doc)]
pub struct Profile {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub describes: Option<AnyObject>,
#[serde(flatten)]
pub inner: Object<ProfileType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[builder(doc)]
pub struct Relationship {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub subject: Option<AnyObject>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub object: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub relationship: Option<OneOrMany<AnyObject>>,
#[serde(flatten)]
pub inner: Object<RelationshipType>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)]
#[builder(doc)]
pub struct Tombstone {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub former_type: Option<OneOrMany<AnyObject>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub deleted: Option<XsdDateTime>,
#[serde(flatten)]
@ -347,6 +397,105 @@ impl Object<serde_json::Value> {
}
impl<Kind> Object<Kind> {
fn extending(mut unparsed: Unparsed) -> Result<Self, serde_json::Error>
where
Kind: serde::de::DeserializeOwned,
{
Ok(Object {
kind: WithUnparsedExt::remove(&mut unparsed, "type")?,
context: WithUnparsedExt::remove(&mut unparsed, "context")?,
id: WithUnparsedExt::remove(&mut unparsed, "id")?,
attachment: WithUnparsedExt::remove(&mut unparsed, "attachment")?,
attributed_to: WithUnparsedExt::remove(&mut unparsed, "attributedTo")?,
audience: WithUnparsedExt::remove(&mut unparsed, "audience")?,
content: WithUnparsedExt::remove(&mut unparsed, "content")?,
name: WithUnparsedExt::remove(&mut unparsed, "name")?,
summary: WithUnparsedExt::remove(&mut unparsed, "summary")?,
url: WithUnparsedExt::remove(&mut unparsed, "url")?,
media_type: WithUnparsedExt::remove(&mut unparsed, "mediaType")?,
generator: WithUnparsedExt::remove(&mut unparsed, "generator")?,
image: WithUnparsedExt::remove(&mut unparsed, "image")?,
location: WithUnparsedExt::remove(&mut unparsed, "location")?,
preview: WithUnparsedExt::remove(&mut unparsed, "preview")?,
start_time: WithUnparsedExt::remove(&mut unparsed, "startTime")?,
end_time: WithUnparsedExt::remove(&mut unparsed, "endTime")?,
duration: WithUnparsedExt::remove(&mut unparsed, "duration")?,
published: WithUnparsedExt::remove(&mut unparsed, "published")?,
updated: WithUnparsedExt::remove(&mut unparsed, "updated")?,
in_reply_to: WithUnparsedExt::remove(&mut unparsed, "inReplyTo")?,
replies: WithUnparsedExt::remove(&mut unparsed, "replies")?,
to: WithUnparsedExt::remove(&mut unparsed, "to")?,
bto: WithUnparsedExt::remove(&mut unparsed, "bto")?,
cc: WithUnparsedExt::remove(&mut unparsed, "cc")?,
bcc: WithUnparsedExt::remove(&mut unparsed, "bcc")?,
unparsed,
})
}
fn retracting(self) -> Result<Unparsed, serde_json::Error>
where
Kind: serde::ser::Serialize,
{
let Object {
kind,
context,
id,
attachment,
attributed_to,
audience,
content,
name,
summary,
url,
media_type,
generator,
image,
location,
preview,
start_time,
end_time,
duration,
published,
updated,
in_reply_to,
replies,
to,
bto,
cc,
bcc,
mut unparsed,
} = self;
WithUnparsedExt::insert(&mut unparsed, "type", kind)?;
WithUnparsedExt::insert(&mut unparsed, "context", context)?;
WithUnparsedExt::insert(&mut unparsed, "id", id)?;
WithUnparsedExt::insert(&mut unparsed, "attachment", attachment)?;
WithUnparsedExt::insert(&mut unparsed, "attributedTo", attributed_to)?;
WithUnparsedExt::insert(&mut unparsed, "audience", audience)?;
WithUnparsedExt::insert(&mut unparsed, "content", content)?;
WithUnparsedExt::insert(&mut unparsed, "name", name)?;
WithUnparsedExt::insert(&mut unparsed, "summary", summary)?;
WithUnparsedExt::insert(&mut unparsed, "url", url)?;
WithUnparsedExt::insert(&mut unparsed, "mediaType", media_type)?;
WithUnparsedExt::insert(&mut unparsed, "generator", generator)?;
WithUnparsedExt::insert(&mut unparsed, "image", image)?;
WithUnparsedExt::insert(&mut unparsed, "location", location)?;
WithUnparsedExt::insert(&mut unparsed, "preview", preview)?;
WithUnparsedExt::insert(&mut unparsed, "startTime", start_time)?;
WithUnparsedExt::insert(&mut unparsed, "endTime", end_time)?;
WithUnparsedExt::insert(&mut unparsed, "duration", duration)?;
WithUnparsedExt::insert(&mut unparsed, "published", published)?;
WithUnparsedExt::insert(&mut unparsed, "updated", updated)?;
WithUnparsedExt::insert(&mut unparsed, "inReplyTo", in_reply_to)?;
WithUnparsedExt::insert(&mut unparsed, "replies", replies)?;
WithUnparsedExt::insert(&mut unparsed, "to", to)?;
WithUnparsedExt::insert(&mut unparsed, "bto", bto)?;
WithUnparsedExt::insert(&mut unparsed, "cc", cc)?;
WithUnparsedExt::insert(&mut unparsed, "bcc", bcc)?;
Ok(unparsed)
}
pub fn into_generic(self) -> Result<Object<serde_json::Value>, serde_json::Error>
where
Kind: serde::ser::Serialize,
@ -611,6 +760,43 @@ impl traits::Object for Relationship {}
impl traits::Base for Tombstone {}
impl traits::Object for Tombstone {}
impl<Kind> Extends<Unparsed> for Object<Kind>
where
Kind: serde::de::DeserializeOwned + serde::ser::Serialize,
{
type Error = serde_json::Error;
fn extends(unparsed: Unparsed) -> Result<Self, Self::Error> {
Self::extending(unparsed)
}
fn retracts(self) -> Result<Unparsed, Self::Error> {
self.retracting()
}
}
impl<Kind> TryFrom<Unparsed> for Object<Kind>
where
Kind: serde::de::DeserializeOwned,
{
type Error = serde_json::Error;
fn try_from(unparsed: Unparsed) -> Result<Self, Self::Error> {
Self::extending(unparsed)
}
}
impl<Kind> TryFrom<Object<Kind>> for Unparsed
where
Kind: serde::ser::Serialize,
{
type Error = serde_json::Error;
fn try_from(object: Object<Kind>) -> Result<Self, Self::Error> {
object.retracting()
}
}
impl<Inner> Extends<Inner> for ApObject<Inner>
where
Inner: WithUnparsed + traits::Object,
@ -646,6 +832,14 @@ impl TryFrom<Object<PlaceType>> for Place {
}
}
impl TryFrom<Place> for Object<PlaceType> {
type Error = serde_json::Error;
fn try_from(place: Place) -> Result<Self, Self::Error> {
place.retracting()
}
}
impl Extends<Object<ProfileType>> for Profile {
type Error = serde_json::Error;
@ -666,6 +860,14 @@ impl TryFrom<Object<ProfileType>> for Profile {
}
}
impl TryFrom<Profile> for Object<ProfileType> {
type Error = serde_json::Error;
fn try_from(profile: Profile) -> Result<Self, Self::Error> {
profile.retracting()
}
}
impl Extends<Object<RelationshipType>> for Relationship {
type Error = serde_json::Error;
@ -686,6 +888,14 @@ impl TryFrom<Object<RelationshipType>> for Relationship {
}
}
impl TryFrom<Relationship> for Object<RelationshipType> {
type Error = serde_json::Error;
fn try_from(relationship: Relationship) -> Result<Self, Self::Error> {
relationship.retracting()
}
}
impl Extends<Object<TombstoneType>> for Tombstone {
type Error = serde_json::Error;
@ -706,6 +916,14 @@ impl TryFrom<Object<TombstoneType>> for Tombstone {
}
}
impl TryFrom<Tombstone> for Object<TombstoneType> {
type Error = serde_json::Error;
fn try_from(tombstone: Tombstone) -> Result<Self, Self::Error> {
tombstone.retracting()
}
}
impl<Kind> WithUnparsed for Object<Kind> {
fn unparsed(&self) -> &Unparsed {
&self.unparsed

View file

@ -1,7 +1,7 @@
use crate::either::Either;
pub use activitystreams::primitives::{
Length, MimeMediaType, RdfLangString, XsdAnyUri, XsdDateTime, XsdDuration,
Length, MimeMediaType, RdfLangString, XsdAnyUri, XsdDateTime, XsdDuration, XsdFloat,
XsdNonNegativeInteger, XsdString,
};
@ -185,6 +185,18 @@ impl<T> OneOrMany<T> {
}
}
impl crate::traits::Base for Unparsed {}
impl crate::traits::WithUnparsed for Unparsed {
fn unparsed(&self) -> &Unparsed {
self
}
fn unparsed_mut(&mut self) -> &mut Unparsed {
self
}
}
impl From<XsdString> for AnyString {
fn from(s: XsdString) -> Self {
AnyString::from_xsd_string(s)