Convert from JSON using impl FromStr and impl TryFrom<&'a str> rather than an inherent from_str method.

This commit is contained in:
Jimmy Cuadra 2019-06-20 22:10:04 -07:00
parent e13acb4d7d
commit d9039db8df
2 changed files with 25 additions and 11 deletions

View File

@ -145,7 +145,7 @@ impl ToTokens for RumaEvent {
let event_type_field_count = if self.is_custom { 0 } else { 1 };
let field_count = event_fields.len() + event_type_field_count;
let mut from_str_field_values: Vec<TokenStream> = Vec::with_capacity(event_fields.len());
let mut try_from_field_values: Vec<TokenStream> = Vec::with_capacity(event_fields.len());
let mut serialize_field_calls: Vec<TokenStream> = Vec::with_capacity(event_fields.len());
for field in event_fields {
@ -159,7 +159,7 @@ impl ToTokens for RumaEvent {
let span = field.span();
let from_str_field_value = if ident == "content" {
let try_from_field_value = if ident == "content" {
match &self.content {
Content::Struct(content_fields) => {
let mut content_field_values: Vec<TokenStream> =
@ -225,7 +225,7 @@ impl ToTokens for RumaEvent {
}
};
from_str_field_values.push(from_str_field_value);
try_from_field_values.push(try_from_field_value);
let serialize_field_call = quote_spanned! {span=>
state.serialize_field(#ident_str, &self.#ident)?;
@ -316,17 +316,28 @@ impl ToTokens for RumaEvent {
#content
impl #name {
impl std::str::FromStr for #name {
type Err = crate::InvalidEvent;
/// Attempt to create `Self` from parsing a string of JSON data.
pub fn from_str(json: &str) -> Result<Self, crate::InvalidEvent> {
fn from_str(json: &str) -> Result<Self, Self::Err> {
let raw = serde_json::from_str::<raw::#name>(json)?;
Ok(Self {
#(#from_str_field_values)*
#(#try_from_field_values)*
})
}
}
impl<'a> std::convert::TryFrom<&'a str> for #name {
type Error = crate::InvalidEvent;
/// Attempt to create `Self` from parsing a string of JSON data.
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
std::str::FromStr::from_str(json)
}
}
use serde::ser::SerializeStruct as _;
impl serde::Serialize for #name {

View File

@ -121,11 +121,14 @@ mod parse;
/// the first.
///
/// The event type and content type will have copies generated inside a private `raw` module. These
/// "raw" versions are the same, except they implement `serde::Deserialize`. An inherent method
/// called `from_str` will be generated for the event type that takes a `&str` of JSON and attempts
/// to deserialize the type using the "raw" version. If deserialization fails, an error is returned
/// to the user. If deserialization succeeds, a value of the public event type will be populated
/// from the raw version's fields and returned.
/// "raw" versions are the same, except they implement `serde::Deserialize`. An implementation of
/// `TryFrom<&str>` will be provided, which (through a blanket implementation in the standard
/// library for `FromStr` will allow the user to call `parse` on a string slice of JSON data in
/// attempt to convert into the event type. `TryFrom<&str>` attempts to deserialize the type using
/// the "raw" version. If deserialization fails, an error is returned to the user. If
/// deserialization succeeds, a value of the public event type will be populated from the raw
/// version's fields and returned. If any semantic error is found after deserialization, a
/// `serde_json::Value` of the deserialized data will be returned in an `InvalidEvent`.
#[proc_macro]
pub fn ruma_event(input: TokenStream) -> TokenStream {
let ruma_event_input = syn::parse_macro_input!(input as RumaEventInput);