use crate::{ either::Either, primitives::{ AnyString, MimeMediaType, OneOrMany, Unit, Unparsed, XsdAnyUri, XsdDateTime, XsdDuration, XsdFloat, XsdString, }, traits::{self, Extends, WithUnparsed, WithUnparsedExt}, }; use std::convert::TryFrom; use typed_builder::TypedBuilder; pub mod kind { pub use activitystreams::object::kind::*; } use self::kind::*; pub type Article = Object; pub type Audio = Object; pub type Document = Object; pub type Event = Object; pub type Image = Object; pub type Note = Object; pub type Page = Object; pub type Video = Object; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(transparent)] struct IdOrObject(Either>>); #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(transparent)] pub struct AnyObject(Either); #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] pub struct Object { #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub context: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub id: Option, #[serde(rename = "type")] #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub kind: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub attachment: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub attributed_to: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub audience: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub content: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub name: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub summary: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub url: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub media_type: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub generator: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub image: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub location: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub preview: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub start_time: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub end_time: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub duration: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub published: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub updated: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub in_reply_to: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub replies: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub to: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub bto: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub cc: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub bcc: Option>, #[serde(flatten)] #[builder(default)] pub unparsed: Unparsed, } #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, TypedBuilder)] #[serde(rename_all = "camelCase")] #[builder(doc)] pub struct ApObject { #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub shares: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub likes: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub source: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub upload_media: Option>, #[serde(flatten)] pub inner: Inner, } #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, TypedBuilder)] #[builder(doc)] pub struct Place { #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub accuracy: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub altitude: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub latitude: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub longitude: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub radius: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub units: Option, #[serde(flatten)] pub inner: Object, } #[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, #[serde(flatten)] pub inner: Object, } #[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, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub object: Option>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub relationship: Option>, #[serde(flatten)] pub inner: Object, } #[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>, #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option, into))] pub deleted: Option, #[serde(flatten)] pub inner: Object, } 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> { self.0.as_ref().left().and_then(|l| l.as_object()) } pub fn id(self) -> Option { self.0.left().and_then(|l| l.id()) } pub fn xsd_string(self) -> Option { self.0.right() } pub fn object(self) -> Option> { 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) { 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) -> 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> { self.0.as_ref().right().map(|b| b.as_ref()) } fn id(self) -> Option { self.0.left() } fn object(self) -> Option> { self.0.right().map(|b| *b) } fn from_xsd_any_uri(id: XsdAnyUri) -> Self { IdOrObject(Either::Left(id)) } fn from_object(object: Object) -> Self { IdOrObject(Either::Right(Box::new(object))) } } impl OneOrMany { 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> { self.as_one().and_then(|inner| inner.as_object()) } pub fn single_xsd_any_uri(self) -> Option { self.one().and_then(|inner| inner.id()) } pub fn single_xsd_string(self) -> Option { self.one().and_then(|inner| inner.xsd_string()) } pub fn single_object(self) -> Option> { 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) -> 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) -> &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) -> &mut Self { self.add(AnyObject::from_object(object)) } } impl Object { pub fn solidify(self) -> Result, serde_json::Error> where Kind: serde::de::DeserializeOwned, { self.try_map_kind(serde_json::from_value) } } impl Object { fn extending(mut unparsed: Unparsed) -> Result 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 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, serde_json::Error> where Kind: serde::ser::Serialize, { self.try_map_kind(serde_json::to_value) } pub fn map_kind(self, f: impl Fn(Kind) -> NewKind) -> Object { 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( self, f: impl Fn(Kind) -> Result, ) -> Result, 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(self) -> Result where Extended: Extends, { Extended::extends(self) } } impl ApObject { fn extending(mut inner: Inner) -> Result 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 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) -> Result { 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, 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) -> Result { let describes = inner.remove("describes")?; Ok(Profile { describes, inner }) } fn retracting(self) -> Result, serde_json::Error> { let Profile { describes, mut inner, } = self; inner.insert("describes", describes)?; Ok(inner) } } impl Relationship { fn extending(mut inner: Object) -> Result { 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, 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) -> Result { let former_type = inner.remove("formerType")?; let deleted = inner.remove("deleted")?; Ok(Tombstone { former_type, deleted, inner, }) } fn retracting(self) -> Result, serde_json::Error> { let Tombstone { former_type, deleted, mut inner, } = self; inner .insert("formerType", former_type)? .insert("deleted", deleted)?; Ok(inner) } } impl traits::Base for Object where Kind: std::fmt::Debug {} impl traits::Object for Object where Kind: std::fmt::Debug {} impl traits::Base for ApObject where Inner: traits::Base {} impl traits::Object for ApObject 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 Extends for Object where Kind: serde::de::DeserializeOwned + serde::ser::Serialize, { type Error = serde_json::Error; fn extends(unparsed: Unparsed) -> Result { Self::extending(unparsed) } fn retracts(self) -> Result { self.retracting() } } impl TryFrom for Object where Kind: serde::de::DeserializeOwned, { type Error = serde_json::Error; fn try_from(unparsed: Unparsed) -> Result { Self::extending(unparsed) } } impl TryFrom> for Unparsed where Kind: serde::ser::Serialize, { type Error = serde_json::Error; fn try_from(object: Object) -> Result { object.retracting() } } impl Extends for ApObject where Inner: WithUnparsed + traits::Object, { type Error = serde_json::Error; fn extends(inner: Inner) -> Result { Self::extending(inner) } fn retracts(self) -> Result { self.retracting() } } impl Extends> for Place { type Error = serde_json::Error; fn extends(object: Object) -> Result { Self::extending(object) } fn retracts(self) -> Result, Self::Error> { self.retracting() } } impl TryFrom> for Place { type Error = serde_json::Error; fn try_from(object: Object) -> Result { Self::extending(object) } } impl TryFrom for Object { type Error = serde_json::Error; fn try_from(place: Place) -> Result { place.retracting() } } impl Extends> for Profile { type Error = serde_json::Error; fn extends(object: Object) -> Result { Self::extending(object) } fn retracts(self) -> Result, Self::Error> { self.retracting() } } impl TryFrom> for Profile { type Error = serde_json::Error; fn try_from(object: Object) -> Result { Self::extending(object) } } impl TryFrom for Object { type Error = serde_json::Error; fn try_from(profile: Profile) -> Result { profile.retracting() } } impl Extends> for Relationship { type Error = serde_json::Error; fn extends(object: Object) -> Result { Self::extending(object) } fn retracts(self) -> Result, Self::Error> { self.retracting() } } impl TryFrom> for Relationship { type Error = serde_json::Error; fn try_from(object: Object) -> Result { Self::extending(object) } } impl TryFrom for Object { type Error = serde_json::Error; fn try_from(relationship: Relationship) -> Result { relationship.retracting() } } impl Extends> for Tombstone { type Error = serde_json::Error; fn extends(object: Object) -> Result { Self::extending(object) } fn retracts(self) -> Result, Self::Error> { self.retracting() } } impl TryFrom> for Tombstone { type Error = serde_json::Error; fn try_from(object: Object) -> Result { Self::extending(object) } } impl TryFrom for Object { type Error = serde_json::Error; fn try_from(tombstone: Tombstone) -> Result { tombstone.retracting() } } impl WithUnparsed for Object { fn unparsed(&self) -> &Unparsed { &self.unparsed } fn unparsed_mut(&mut self) -> &mut Unparsed { &mut self.unparsed } } impl WithUnparsed for ApObject 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> for AnyObject { fn from(o: Object) -> Self { Self::from_object(o) } } impl From for AnyObject { fn from(id: XsdAnyUri) -> Self { Self::from_xsd_any_uri(id) } } impl From for AnyObject { fn from(xsd_string: XsdString) -> Self { Self::from_xsd_string(xsd_string) } } impl From> for OneOrMany { fn from(object: Object) -> Self { Self::from_object(object) } } impl From for OneOrMany { fn from(xsd_any_uri: XsdAnyUri) -> Self { Self::from_xsd_any_uri(xsd_any_uri) } } impl From for OneOrMany { fn from(xsd_string: XsdString) -> Self { Self::from_xsd_string(xsd_string) } }