Simplify fetching properties

This commit is contained in:
asonix 2018-05-13 14:53:06 -05:00
parent 0ac25889c1
commit 4e2b965100
37 changed files with 105 additions and 192 deletions

View file

@ -157,7 +157,7 @@ pub fn properties_derive(input: TokenStream) -> TokenStream {
_ => panic!("Can only derive for named fields"),
};
let getters = fields
let impls = fields
.named
.iter()
.filter_map(|field| {
@ -220,80 +220,88 @@ pub fn properties_derive(input: TokenStream) -> TokenStream {
let fn_plural = Ident::from(format!("{}_{}_vec", ident, lower_variant));
let variant = Ident::from(variant);
if is_concrete && is_option && is_functional {
quote! {
pub fn #fn_name(&self) -> Result<#variant> {
self.get_item(|t| &t.#ident)
}
}
} else if is_concrete && is_option {
quote! {
pub fn #fn_name(&self) -> Result<#variant> {
self.get_item(|t| &t.#ident)
if is_concrete && is_option {
let single = quote! {
pub fn #fn_name(&self) -> ::error::Result<#variant> {
::properties::get_item(&self.#ident)
}
};
pub fn #fn_plural(&self) -> Result<Vec<#variant>> {
self.get_item(|t| &t.#ident)
if is_functional {
single
} else {
quote! {
#single
pub fn #fn_plural(&self) -> ::error::Result<Vec<#variant>> {
::properties::get_item(&self.#ident)
}
}
}
} else if is_concrete && is_vec {
quote! {
pub fn #fn_name(&self) -> Result<Vec<#variant>> {
self.get_vec(|t| &t.#ident)
}
}
} else if is_concrete && is_functional {
quote! {
pub fn #fn_name(&self) -> Result<#variant> {
self.get_value(|t| &t.#ident)
pub fn #fn_name(&self) -> ::error::Result<Vec<#variant>> {
::properties::get_vec(&self.#ident)
}
}
} else if is_concrete {
quote! {
pub fn #fn_name(&self) -> Result<#variant> {
self.get_value(|t| &t.#ident)
let single = quote! {
pub fn #fn_name(&self) -> ::error::Result<#variant> {
::properties::get_value(&self.#ident)
}
};
pub fn #fn_plural(&self) -> Result<Vec<#variant>> {
self.get_value(|t| &t.#ident)
}
}
} else if is_option && is_functional {
if is_functional {
single
} else {
quote! {
pub fn #fn_name<T: #variant>(&self) -> Result<T> {
self.get_item(|t| &t.#ident)
#single
pub fn #fn_plural(&self) -> ::error::Result<Vec<#variant>> {
::properties::get_value(&self.#ident)
}
}
}
} else if is_option {
quote! {
pub fn #fn_name<T: #variant>(&self) -> Result<T> {
self.get_item(|t| &t.#ident)
let single = quote! {
pub fn #fn_name<T: #variant>(&self) -> ::error::Result<T> {
::properties::get_item(&self.#ident)
}
};
pub fn #fn_plural<T: #variant>(&self) -> Result<Vec<T>> {
self.get_item(|t| &t.#ident)
if is_functional {
single
} else {
quote! {
#single
pub fn #fn_plural<T: #variant>(&self) -> ::error::Result<Vec<T>> {
::properties::get_item(&self.#ident)
}
}
}
} else if is_vec {
quote! {
pub fn #fn_name<T: #variant>(&self) -> Result<Vec<T>> {
self.get_vec(|t| &t.#ident)
}
}
} else if is_functional {
quote! {
pub fn #fn_name<T: #variant>(&self) -> Result<T> {
self.get_value(|t| &t.#ident)
pub fn #fn_name<T: #variant>(&self) -> ::error::Result<Vec<T>> {
::properties::get_vec(&self.#ident)
}
}
} else {
quote! {
pub fn #fn_name<T: #variant>(&self) -> Result<T> {
self.get_value(|t| &t.#ident)
let single = quote! {
pub fn #fn_name<T: #variant>(&self) -> ::error::Result<T> {
::properties::get_value(&self.#ident)
}
};
pub fn #fn_plural<T: #variant>(&self) -> Result<Vec<T>> {
self.get_value(|t| &t.#ident)
if is_functional {
single
} else {
quote! {
#single
pub fn #fn_plural<T: #variant>(&self) -> ::error::Result<Vec<T>> {
::properties::get_value(&self.#ident)
}
}
}
}
@ -301,11 +309,9 @@ pub fn properties_derive(input: TokenStream) -> TokenStream {
});
let mut tokens = Tokens::new();
tokens.append_all(getters);
tokens.append_all(impls);
let full = quote!{
impl Properties for #name {}
impl #name {
#tokens
}

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::AcceptType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::AddType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::MoveType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::AnnounceType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::ArriveType, properties::ActivityProperties, Activity, IntransitiveActivity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::BlockType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::CreateType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::DeleteType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::DislikeType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::FlagType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::FollowType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::IgnoreType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::InviteType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::JoinType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::LeaveType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::LikeType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::ListenType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::OfferType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -19,10 +19,8 @@
use serde_json;
use error::Result;
use link::Link;
use object::Object;
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::QuestionType, properties::ActivityProperties, Activity, IntransitiveActivity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::ReadType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::RejectType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::RemoveType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::TentativeAcceptType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::TentativeRejectType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::TravelType, properties::ActivityProperties, Activity, IntransitiveActivity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::UndoType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::UpdateType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -21,10 +21,8 @@ use serde_json;
use super::{kind::ViewType, properties::ActivityProperties, Activity};
use error::Result;
use link::Link;
use object::{Object, ObjectProperties};
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -19,7 +19,6 @@
use serde_json;
use error::Result;
use link::Link;
use object::Object;
@ -27,7 +26,6 @@ mod kind;
mod properties;
pub use self::kind::*;
pub use self::properties::*;
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -20,9 +20,7 @@
use serde_json;
use super::{Collection, CollectionPage};
use error::Result;
use link::Link;
use Properties;
#[derive(Clone, Debug, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -35,50 +35,10 @@ pub fn context() -> serde_json::Value {
})
}
pub trait Properties {
fn get_value<F, I>(&self, f: F) -> error::Result<I>
where
F: FnOnce(&Self) -> &serde_json::Value,
I: serde::de::DeserializeOwned,
{
serde_json::from_value(f(self).clone()).map_err(|_| error::Error::Deserialize)
}
fn get_item<F, I>(&self, f: F) -> error::Result<I>
where
F: FnOnce(&Self) -> &Option<serde_json::Value>,
I: serde::de::DeserializeOwned,
{
if let &Some(ref item) = f(self) {
serde_json::from_value(item.clone()).map_err(|_| error::Error::Deserialize)
} else {
Err(error::Error::NotFound)
}
}
fn get_vec<F, I>(&self, f: F) -> error::Result<Vec<I>>
where
F: FnOnce(&Self) -> &Vec<serde_json::Value>,
I: serde::de::DeserializeOwned,
{
let item = f(self);
item.iter().fold(Ok(Vec::new()), |acc, item| match acc {
Ok(mut acc) => match serde_json::from_value(item.clone()) {
Ok(item) => {
acc.push(item);
Ok(acc)
}
Err(_) => Err(error::Error::Deserialize),
},
Err(e) => Err(e),
})
}
}
pub mod activity;
pub mod actor;
pub mod collection;
pub mod error;
pub mod link;
pub mod object;
pub mod properties;

View file

@ -23,7 +23,6 @@ use serde_json;
use error::{Error, Result};
use link::Link;
use object::Object;
use Properties;
#[derive(Clone, Debug, Serialize, Deserialize, Properties)]
#[serde(rename_all = "camelCase")]

View file

@ -20,9 +20,7 @@
use serde::{de::DeserializeOwned, ser::Serialize};
use serde_json;
use error::Result;
use link::Link;
use Properties;
mod kind;
mod properties;

View file

@ -25,7 +25,8 @@ use collection::Collection;
use error::{Error, Result};
use link::Link;
use object::{Image, Object};
use Properties;
pub type UtcTime = DateTime<Utc>;
#[derive(Clone, Debug, Serialize, Deserialize, Properties)]
#[serde(rename_all = "camelCase")]
@ -59,7 +60,7 @@ pub struct ObjectProperties {
name: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
#[activitystreams(concrete(String), functional)]
#[activitystreams(concrete(String, UtcTime), functional)]
end_time: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
@ -87,7 +88,7 @@ pub struct ObjectProperties {
preview: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
#[activitystreams(concrete(String), functional)]
#[activitystreams(concrete(String, UtcTime), functional)]
published: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
@ -95,7 +96,7 @@ pub struct ObjectProperties {
replies: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
#[activitystreams(concrete(String), functional)]
#[activitystreams(concrete(String, UtcTime), functional)]
start_time: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
@ -107,7 +108,7 @@ pub struct ObjectProperties {
tag: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
#[activitystreams(concrete(String), functional)]
#[activitystreams(concrete(String, UtcTime), functional)]
updated: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
@ -145,26 +146,6 @@ impl ObjectProperties {
self.media_type_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
pub fn end_time(&self) -> Result<DateTime<Utc>> {
self.end_time_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
pub fn published(&self) -> Result<DateTime<Utc>> {
self.published_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
pub fn start_time(&self) -> Result<DateTime<Utc>> {
self.start_time_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
pub fn updated(&self) -> Result<DateTime<Utc>> {
self.updated_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Properties)]
@ -199,13 +180,6 @@ pub struct TombstoneProperties {
former_type: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
#[activitystreams(concrete(String), functional)]
#[activitystreams(concrete(String, UtcTime), functional)]
deleted: Option<serde_json::Value>,
}
impl TombstoneProperties {
pub fn deleted(&self) -> Result<DateTime<Utc>> {
self.deleted_string()
.and_then(|s| s.parse().map_err(|_| Error::Deserialize))
}
}

38
src/properties.rs Normal file
View file

@ -0,0 +1,38 @@
use serde::de::DeserializeOwned;
use serde_json;
use error::{Error, Result};
pub fn get_value<I>(item: &serde_json::Value) -> Result<I>
where
I: DeserializeOwned,
{
serde_json::from_value(item.clone()).map_err(|_| Error::Deserialize)
}
pub fn get_item<I>(item: &Option<serde_json::Value>) -> Result<I>
where
I: DeserializeOwned,
{
if let &Some(ref item) = item {
serde_json::from_value(item.clone()).map_err(|_| Error::Deserialize)
} else {
Err(Error::NotFound)
}
}
pub fn get_vec<I>(v: &Vec<serde_json::Value>) -> Result<Vec<I>>
where
I: DeserializeOwned,
{
v.iter().fold(Ok(Vec::new()), |acc, item| match acc {
Ok(mut acc) => match serde_json::from_value(item.clone()) {
Ok(item) => {
acc.push(item);
Ok(acc)
}
Err(_) => Err(Error::Deserialize),
},
Err(e) => Err(e),
})
}