Move raw mod into FromRaw derive

This commit is contained in:
Ragotzy.devin 2020-05-16 02:33:04 -04:00 committed by Jonas Platte
parent 1a9b0f3e8b
commit f0c94958fa
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
6 changed files with 37 additions and 85 deletions

View File

@ -15,6 +15,16 @@ pub fn expand_from_raw(input: DeriveInput) -> syn::Result<TokenStream> {
};
let ident = &input.ident;
let raw_content = {
let fields = fields.iter();
quote! {
#[derive(Clone, Debug, serde::Deserialize)]
pub struct #ident {
#(#fields),*
}
}
};
let init_list = fields.iter().map(|field| {
let field_ident = field.ident.as_ref().unwrap();
let field_span = field.span();
@ -44,5 +54,11 @@ pub fn expand_from_raw(input: DeriveInput) -> syn::Result<TokenStream> {
}
}
}
pub(crate) mod raw {
use super::*;
#raw_content
}
})
}

View File

@ -3,12 +3,11 @@
#![allow(dead_code)]
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use quote::{format_ident, quote, ToTokens};
use syn::{
parse::{self, Parse, ParseStream},
parse_quote,
punctuated::Punctuated,
spanned::Spanned,
Attribute, Field, Ident, LitStr, Token,
};
@ -87,10 +86,9 @@ impl ToTokens for RumaEvent {
let content = match &self.content {
Content::Struct(fields) => {
// TODO remove serde::Deserialize when this macro actually generates generic events
quote! {
#[doc = #content_docstring]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Debug, serde::Serialize, ::ruma_events_macros::FromRaw)]
pub struct #content_name {
#(#fields),*
}
@ -107,67 +105,9 @@ impl ToTokens for RumaEvent {
}
};
let raw_content = match &self.content {
Content::Struct(fields) => {
quote! {
#[doc = #content_docstring]
#[derive(Clone, Debug, serde::Deserialize)]
pub struct #content_name {
#(#fields),*
}
}
}
Content::Typedef(_) => TokenStream::new(),
};
let impl_event_result_compatible_for_content =
if let Content::Struct(content_fields) = &self.content {
let mut content_field_values: Vec<TokenStream> =
Vec::with_capacity(content_fields.len());
for content_field in content_fields {
let content_field_ident = content_field.ident.clone().unwrap();
let span = content_field.span();
let token_stream = quote_spanned! {span=>
#content_field_ident: raw.#content_field_ident,
};
content_field_values.push(token_stream);
}
quote! {
impl ::ruma_events::FromRaw for #content_name {
type Raw = raw::#content_name;
fn from_raw(
raw: raw::#content_name
) -> Self {
Self {
#(#content_field_values)*
}
}
}
}
} else {
TokenStream::new()
};
// let event_type_name = self.event_type.value();
let output = quote!(
#content
#impl_event_result_compatible_for_content
/// "Raw" versions of the event and its content which implement `serde::Deserialize`.
pub(crate) mod raw {
use super::*;
#raw_content
}
);
output.to_tokens(tokens);
content.to_tokens(tokens);
}
}

View File

@ -120,10 +120,11 @@ use std::fmt::Debug;
use js_int::Int;
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue;
// use self::room::redaction::RedactionEvent;
pub use self::custom::{CustomEvent, CustomRoomEvent, CustomStateEvent};
// pub use self::custom::{CustomEvent, CustomRoomEvent, CustomStateEvent};
#[deprecated = "Use ruma_serde::empty::Empty directly instead."]
pub use ruma_serde::empty::Empty;
@ -141,7 +142,7 @@ pub mod util;
extern crate self as ruma_events;
pub mod call;
pub mod custom;
// pub mod custom;
/// Enums for heterogeneous collections of events.
// pub mod collections {
// pub mod all;
@ -217,10 +218,7 @@ impl UnsignedData {
/// Implementing this trait allows content types to be serialized as well as deserialized.
pub trait EventContent: Sized + Serialize {
/// Constructs the given event content.
fn from_parts(
event_type: &str,
content: &serde_json::value::RawValue,
) -> Result<Self, InvalidEvent>;
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent>;
/// A matrix event identifier, like `m.room.message`.
fn event_type(&self) -> &str;

View File

@ -6,7 +6,7 @@ use serde_json::value::RawValue as RawJsonValue;
use crate::{
error::{InvalidEvent, InvalidEventKind},
EventContent, RoomEventContent, StateEventContent,
EventContent, EventJson, RoomEventContent, StateEventContent,
};
ruma_event! {
@ -26,17 +26,16 @@ impl EventContent for AliasesEventContent {
"m.room.aliases"
}
fn from_parts(event_type: &str, content: &RawJsonValue) -> Result<Self, InvalidEvent> {
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent> {
if event_type != "m.room.aliases" {
return Err(InvalidEvent {
kind: InvalidEventKind::Deserialization,
message: format!("expected `m.room.aliases` found {}", event_type),
});
}
serde_json::from_str::<AliasesEventContent>(content.get()).map_err(|e| InvalidEvent {
kind: InvalidEventKind::Deserialization,
message: e.to_string(),
})
let ev_json = EventJson::from(content);
ev_json.deserialize()
}
}

View File

@ -6,7 +6,7 @@ use serde_json::value::RawValue as RawJsonValue;
use super::ImageInfo;
use crate::{
error::{InvalidEvent, InvalidEventKind},
EventContent, RoomEventContent, StateEventContent,
EventContent, EventJson, RoomEventContent, StateEventContent,
};
ruma_event! {
@ -33,17 +33,16 @@ impl EventContent for AvatarEventContent {
"m.room.avatar"
}
fn from_parts(event_type: &str, content: &RawJsonValue) -> Result<Self, InvalidEvent> {
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent> {
if event_type != "m.room.avatar" {
return Err(InvalidEvent {
kind: InvalidEventKind::Deserialization,
message: format!("expected `m.room.avatar` found {}", event_type),
});
}
serde_json::from_str::<AvatarEventContent>(content.get()).map_err(|e| InvalidEvent {
kind: InvalidEventKind::Deserialization,
message: e.to_string(),
})
let ev_json = EventJson::from(content);
ev_json.deserialize()
}
}

View File

@ -115,10 +115,10 @@ impl EventContent for AnyStateEventContent {
}
}
fn from_parts(event_type: &str, content: &RawJsonValue) -> Result<Self, InvalidEvent> {
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent> {
fn deserialize_variant<T: StateEventContent>(
ev_type: &str,
input: &RawJsonValue,
input: Box<RawJsonValue>,
variant: fn(T) -> AnyStateEventContent,
) -> Result<AnyStateEventContent, InvalidEvent> {
let content = T::from_parts(ev_type, input)?;
@ -278,7 +278,7 @@ impl<'de, C: StateEventContent> Visitor<'de> for StateEventVisitor<C> {
let event_type = event_type.ok_or_else(|| de::Error::missing_field("type"))?;
let raw = content.ok_or_else(|| de::Error::missing_field("content"))?;
let content = C::from_parts(&event_type, &raw).map_err(A::Error::custom)?;
let content = C::from_parts(&event_type, raw).map_err(A::Error::custom)?;
let event_id = event_id.ok_or_else(|| de::Error::missing_field("event_id"))?;
let sender = sender.ok_or_else(|| de::Error::missing_field("sender"))?;
@ -291,7 +291,7 @@ impl<'de, C: StateEventContent> Visitor<'de> for StateEventVisitor<C> {
let state_key = state_key.ok_or_else(|| de::Error::missing_field("state_key"))?;
let prev_content = if let Some(raw) = prev_content {
Some(C::from_parts(&event_type, &raw).map_err(A::Error::custom)?)
Some(C::from_parts(&event_type, raw).map_err(A::Error::custom)?)
} else {
None
};