activitystreams-new/src/object.rs

807 lines
22 KiB
Rust
Raw Normal View History

2020-05-14 03:54:50 +00:00
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)
}
}