Move raw
mod into FromRaw derive
This commit is contained in:
parent
1a9b0f3e8b
commit
f0c94958fa
@ -15,6 +15,16 @@ pub fn expand_from_raw(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
};
|
};
|
||||||
let ident = &input.ident;
|
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 init_list = fields.iter().map(|field| {
|
||||||
let field_ident = field.ident.as_ref().unwrap();
|
let field_ident = field.ident.as_ref().unwrap();
|
||||||
let field_span = field.span();
|
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
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,11 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::{self, Parse, ParseStream},
|
parse::{self, Parse, ParseStream},
|
||||||
parse_quote,
|
parse_quote,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
spanned::Spanned,
|
|
||||||
Attribute, Field, Ident, LitStr, Token,
|
Attribute, Field, Ident, LitStr, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,10 +86,9 @@ impl ToTokens for RumaEvent {
|
|||||||
|
|
||||||
let content = match &self.content {
|
let content = match &self.content {
|
||||||
Content::Struct(fields) => {
|
Content::Struct(fields) => {
|
||||||
// TODO remove serde::Deserialize when this macro actually generates generic events
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #content_docstring]
|
#[doc = #content_docstring]
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, serde::Serialize, ::ruma_events_macros::FromRaw)]
|
||||||
pub struct #content_name {
|
pub struct #content_name {
|
||||||
#(#fields),*
|
#(#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 event_type_name = self.event_type.value();
|
||||||
let output = quote!(
|
|
||||||
#content
|
|
||||||
|
|
||||||
#impl_event_result_compatible_for_content
|
content.to_tokens(tokens);
|
||||||
|
|
||||||
/// "Raw" versions of the event and its content which implement `serde::Deserialize`.
|
|
||||||
pub(crate) mod raw {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#raw_content
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
output.to_tokens(tokens);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/lib.rs
10
src/lib.rs
@ -120,10 +120,11 @@ use std::fmt::Debug;
|
|||||||
|
|
||||||
use js_int::Int;
|
use js_int::Int;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::value::RawValue as RawJsonValue;
|
||||||
|
|
||||||
// use self::room::redaction::RedactionEvent;
|
// 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."]
|
#[deprecated = "Use ruma_serde::empty::Empty directly instead."]
|
||||||
pub use ruma_serde::empty::Empty;
|
pub use ruma_serde::empty::Empty;
|
||||||
@ -141,7 +142,7 @@ pub mod util;
|
|||||||
extern crate self as ruma_events;
|
extern crate self as ruma_events;
|
||||||
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
pub mod custom;
|
// pub mod custom;
|
||||||
/// Enums for heterogeneous collections of events.
|
/// Enums for heterogeneous collections of events.
|
||||||
// pub mod collections {
|
// pub mod collections {
|
||||||
// pub mod all;
|
// pub mod all;
|
||||||
@ -217,10 +218,7 @@ impl UnsignedData {
|
|||||||
/// Implementing this trait allows content types to be serialized as well as deserialized.
|
/// Implementing this trait allows content types to be serialized as well as deserialized.
|
||||||
pub trait EventContent: Sized + Serialize {
|
pub trait EventContent: Sized + Serialize {
|
||||||
/// Constructs the given event content.
|
/// Constructs the given event content.
|
||||||
fn from_parts(
|
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent>;
|
||||||
event_type: &str,
|
|
||||||
content: &serde_json::value::RawValue,
|
|
||||||
) -> Result<Self, InvalidEvent>;
|
|
||||||
|
|
||||||
/// A matrix event identifier, like `m.room.message`.
|
/// A matrix event identifier, like `m.room.message`.
|
||||||
fn event_type(&self) -> &str;
|
fn event_type(&self) -> &str;
|
||||||
|
@ -6,7 +6,7 @@ use serde_json::value::RawValue as RawJsonValue;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{InvalidEvent, InvalidEventKind},
|
error::{InvalidEvent, InvalidEventKind},
|
||||||
EventContent, RoomEventContent, StateEventContent,
|
EventContent, EventJson, RoomEventContent, StateEventContent,
|
||||||
};
|
};
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
@ -26,17 +26,16 @@ impl EventContent for AliasesEventContent {
|
|||||||
"m.room.aliases"
|
"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" {
|
if event_type != "m.room.aliases" {
|
||||||
return Err(InvalidEvent {
|
return Err(InvalidEvent {
|
||||||
kind: InvalidEventKind::Deserialization,
|
kind: InvalidEventKind::Deserialization,
|
||||||
message: format!("expected `m.room.aliases` found {}", event_type),
|
message: format!("expected `m.room.aliases` found {}", event_type),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
serde_json::from_str::<AliasesEventContent>(content.get()).map_err(|e| InvalidEvent {
|
|
||||||
kind: InvalidEventKind::Deserialization,
|
let ev_json = EventJson::from(content);
|
||||||
message: e.to_string(),
|
ev_json.deserialize()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use serde_json::value::RawValue as RawJsonValue;
|
|||||||
use super::ImageInfo;
|
use super::ImageInfo;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{InvalidEvent, InvalidEventKind},
|
error::{InvalidEvent, InvalidEventKind},
|
||||||
EventContent, RoomEventContent, StateEventContent,
|
EventContent, EventJson, RoomEventContent, StateEventContent,
|
||||||
};
|
};
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
@ -33,17 +33,16 @@ impl EventContent for AvatarEventContent {
|
|||||||
"m.room.avatar"
|
"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" {
|
if event_type != "m.room.avatar" {
|
||||||
return Err(InvalidEvent {
|
return Err(InvalidEvent {
|
||||||
kind: InvalidEventKind::Deserialization,
|
kind: InvalidEventKind::Deserialization,
|
||||||
message: format!("expected `m.room.avatar` found {}", event_type),
|
message: format!("expected `m.room.avatar` found {}", event_type),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
serde_json::from_str::<AvatarEventContent>(content.get()).map_err(|e| InvalidEvent {
|
|
||||||
kind: InvalidEventKind::Deserialization,
|
let ev_json = EventJson::from(content);
|
||||||
message: e.to_string(),
|
ev_json.deserialize()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>(
|
fn deserialize_variant<T: StateEventContent>(
|
||||||
ev_type: &str,
|
ev_type: &str,
|
||||||
input: &RawJsonValue,
|
input: Box<RawJsonValue>,
|
||||||
variant: fn(T) -> AnyStateEventContent,
|
variant: fn(T) -> AnyStateEventContent,
|
||||||
) -> Result<AnyStateEventContent, InvalidEvent> {
|
) -> Result<AnyStateEventContent, InvalidEvent> {
|
||||||
let content = T::from_parts(ev_type, input)?;
|
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 event_type = event_type.ok_or_else(|| de::Error::missing_field("type"))?;
|
||||||
|
|
||||||
let raw = content.ok_or_else(|| de::Error::missing_field("content"))?;
|
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 event_id = event_id.ok_or_else(|| de::Error::missing_field("event_id"))?;
|
||||||
let sender = sender.ok_or_else(|| de::Error::missing_field("sender"))?;
|
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 state_key = state_key.ok_or_else(|| de::Error::missing_field("state_key"))?;
|
||||||
|
|
||||||
let prev_content = if let Some(raw) = prev_content {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user