Convert from JSON using impl FromStr and impl TryFrom<&'a str> rather than an inherent from_str method.
This commit is contained in:
parent
e13acb4d7d
commit
d9039db8df
23
src/gen.rs
23
src/gen.rs
@ -145,7 +145,7 @@ impl ToTokens for RumaEvent {
|
|||||||
let event_type_field_count = if self.is_custom { 0 } else { 1 };
|
let event_type_field_count = if self.is_custom { 0 } else { 1 };
|
||||||
let field_count = event_fields.len() + event_type_field_count;
|
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());
|
let mut serialize_field_calls: Vec<TokenStream> = Vec::with_capacity(event_fields.len());
|
||||||
|
|
||||||
for field in event_fields {
|
for field in event_fields {
|
||||||
@ -159,7 +159,7 @@ impl ToTokens for RumaEvent {
|
|||||||
|
|
||||||
let span = field.span();
|
let span = field.span();
|
||||||
|
|
||||||
let from_str_field_value = if ident == "content" {
|
let try_from_field_value = if ident == "content" {
|
||||||
match &self.content {
|
match &self.content {
|
||||||
Content::Struct(content_fields) => {
|
Content::Struct(content_fields) => {
|
||||||
let mut content_field_values: Vec<TokenStream> =
|
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=>
|
let serialize_field_call = quote_spanned! {span=>
|
||||||
state.serialize_field(#ident_str, &self.#ident)?;
|
state.serialize_field(#ident_str, &self.#ident)?;
|
||||||
@ -316,17 +316,28 @@ impl ToTokens for RumaEvent {
|
|||||||
|
|
||||||
#content
|
#content
|
||||||
|
|
||||||
impl #name {
|
impl std::str::FromStr for #name {
|
||||||
|
type Err = crate::InvalidEvent;
|
||||||
|
|
||||||
/// Attempt to create `Self` from parsing a string of JSON data.
|
/// 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)?;
|
let raw = serde_json::from_str::<raw::#name>(json)?;
|
||||||
|
|
||||||
Ok(Self {
|
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 _;
|
use serde::ser::SerializeStruct as _;
|
||||||
|
|
||||||
impl serde::Serialize for #name {
|
impl serde::Serialize for #name {
|
||||||
|
13
src/lib.rs
13
src/lib.rs
@ -121,11 +121,14 @@ mod parse;
|
|||||||
/// the first.
|
/// the first.
|
||||||
///
|
///
|
||||||
/// The event type and content type will have copies generated inside a private `raw` module. These
|
/// 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
|
/// "raw" versions are the same, except they implement `serde::Deserialize`. An implementation of
|
||||||
/// called `from_str` will be generated for the event type that takes a `&str` of JSON and attempts
|
/// `TryFrom<&str>` will be provided, which (through a blanket implementation in the standard
|
||||||
/// to deserialize the type using the "raw" version. If deserialization fails, an error is returned
|
/// library for `FromStr` will allow the user to call `parse` on a string slice of JSON data in
|
||||||
/// to the user. If deserialization succeeds, a value of the public event type will be populated
|
/// attempt to convert into the event type. `TryFrom<&str>` attempts to deserialize the type using
|
||||||
/// from the raw version's fields and returned.
|
/// 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]
|
#[proc_macro]
|
||||||
pub fn ruma_event(input: TokenStream) -> TokenStream {
|
pub fn ruma_event(input: TokenStream) -> TokenStream {
|
||||||
let ruma_event_input = syn::parse_macro_input!(input as RumaEventInput);
|
let ruma_event_input = syn::parse_macro_input!(input as RumaEventInput);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user