Enforce map structure for *Box

This commit is contained in:
asonix 2020-03-14 14:35:56 -05:00
parent df0ef98643
commit a4031c43f2

View file

@ -154,7 +154,7 @@ pub fn ref_derive(input: TokenStream) -> TokenStream {
impl #object for #name {} impl #object for #name {}
impl std::convert::TryFrom<#name> for #box_name { impl std::convert::TryFrom<#name> for #box_name {
type Error = serde_json::Error; type Error = std::io::Error;
fn try_from(s: #name) -> Result<Self, Self::Error> { fn try_from(s: #name) -> Result<Self, Self::Error> {
#box_name::from_concrete(s) #box_name::from_concrete(s)
@ -220,30 +220,17 @@ pub fn ref_derive(input: TokenStream) -> TokenStream {
/// pub struct ObjectBox(pub serde_json::Value); /// pub struct ObjectBox(pub serde_json::Value);
/// ///
/// impl ObjectBox { /// impl ObjectBox {
/// pub fn from_concrete<T>(t: T) -> Result<Self, serde_json::Error> /// pub fn from_concrete<T>(t: T) -> Result<Self, std::io::Error>
/// where /// where
/// T: Object + serde::ser::Serialize, /// T: Object + serde::ser::Serialize;
/// {
/// Ok(ObjectBox(serde_json::to_value(t)?))
/// }
/// ///
/// pub fn to_concrete<T>(self) -> Result<T, serde_json::Error> /// pub fn to_concrete<T>(self) -> Result<T, std::io::Error>
/// where /// where
/// T: Object + serde::de::DeserializeOwned, /// T: Object + serde::de::DeserializeOwned;
/// {
/// serde_json::from_value(self.0)
/// }
/// ///
/// pub fn is_type(&self, kind: impl std::fmt::Display) -> bool { /// pub fn is_type(&self, kind: impl std::fmt::Display) -> bool;
/// self.0["type"] == kind.to_string()
/// }
/// ///
/// pub fn type(&self) -> Option<&str> { /// pub fn type(&self) -> Option<&str>;
/// match self.0["type"] {
/// serde_json::Value::String(ref s) -> Some(s),
/// _ => None,
/// }
/// }
/// } /// }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn wrapper_type(_: TokenStream, input: TokenStream) -> TokenStream { pub fn wrapper_type(_: TokenStream, input: TokenStream) -> TokenStream {
@ -258,28 +245,31 @@ pub fn wrapper_type(_: TokenStream, input: TokenStream) -> TokenStream {
#doc_line #doc_line
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)] #[serde(transparent)]
pub struct #type_name(pub serde_json::Value); pub struct #type_name(serde_json::Map<String, serde_json::Value>);
impl #type_name { impl #type_name {
/// Coerce a concrete type into this wrapper type /// Coerce a concrete type into this wrapper type
/// ///
/// This is done automatically via TryFrom in proprties setter methods /// This is done automatically via TryFrom in proprties setter methods
pub fn from_concrete<T>(t: T) -> Result<Self, serde_json::Error> pub fn from_concrete<T>(t: T) -> Result<Self, std::io::Error>
where where
T: #trait_name + serde::ser::Serialize, T: #trait_name + serde::ser::Serialize,
{ {
Ok(#type_name(serde_json::to_value(t)?)) match serde_json::to_value(t)? {
serde_json::Value::Object(map) => Ok(#type_name(map)),
_ => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Not an object")),
}
} }
/// Attempt to deserialize the wrapper type to a concrete type /// Attempt to deserialize the wrapper type to a concrete type
/// ///
/// Before this method is called, the type should be verified via the `kind` or /// Before this method is called, the type should be verified via the `kind` or
/// `is_kind` methods /// `is_kind` methods
pub fn to_concrete<T>(self) -> Result<T, serde_json::Error> pub fn to_concrete<T>(self) -> Result<T, std::io::Error>
where where
T: #trait_name + serde::de::DeserializeOwned, T: #trait_name + serde::de::DeserializeOwned,
{ {
serde_json::from_value(self.0) Ok(serde_json::from_value(serde_json::Value::Object(self.0))?)
} }
/// Return whether the given wrapper type is expected. /// Return whether the given wrapper type is expected.