events: Fix serde of event types with suffix

This commit is contained in:
Kévin Commaille 2022-05-09 12:41:22 +02:00 committed by GitHub
parent 20b8c298d2
commit abf735093c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 120 additions and 37 deletions

View File

@ -101,7 +101,7 @@ mod tests {
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{PassPhrase, SecretEncryptionAlgorithm, SecretStorageKeyEventContent};
use crate::{serde::Base64, KeyDerivationAlgorithm};
use crate::{events::GlobalAccountDataEvent, serde::Base64, KeyDerivationAlgorithm};
#[test]
fn test_key_description_serialization() {
@ -218,4 +218,62 @@ mod tests {
&& bits == uint!(256)
)
}
#[test]
fn test_event_serialization() {
let event = GlobalAccountDataEvent {
content: SecretStorageKeyEventContent::new(
"my_key_id".into(),
"my_key".into(),
SecretEncryptionAlgorithm::SecretStorageV1AesHmacSha2 {
iv: Base64::parse("YWJjZGVmZ2hpamtsbW5vcA").unwrap(),
mac: Base64::parse("aWRvbnRrbm93d2hhdGFtYWNsb29rc2xpa2U").unwrap(),
},
),
};
let json = json!({
"type": "m.secret_storage.key.my_key_id",
"content": {
"name": "my_key",
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
"iv": "YWJjZGVmZ2hpamtsbW5vcA",
"mac": "aWRvbnRrbm93d2hhdGFtYWNsb29rc2xpa2U"
}
});
assert_eq!(to_json_value(&event).unwrap(), json);
}
#[test]
fn test_event_deserialization() {
let json = json!({
"type": "m.secret_storage.key.my_key_id",
"content": {
"name": "my_key",
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
"iv": "YWJjZGVmZ2hpamtsbW5vcA",
"mac": "aWRvbnRrbm93d2hhdGFtYWNsb29rc2xpa2U"
}
});
assert_matches!(
from_json_value(json).unwrap(),
GlobalAccountDataEvent {
content: SecretStorageKeyEventContent {
key_id,
name,
algorithm: SecretEncryptionAlgorithm::SecretStorageV1AesHmacSha2 {
iv,
mac,
},
passphrase: None,
}
}
if key_id == *"my_key_id"
&& name == *"my_key"
&& iv == Base64::parse("YWJjZGVmZ2hpamtsbW5vcA").unwrap()
&& mac == Base64::parse("aWRvbnRrbm93d2hhdGFtYWNsb29rc2xpa2U").unwrap()
)
}
}

View File

@ -483,13 +483,10 @@ fn generate_event_content_impl<'a>(
let (event_type_ty_decl, event_type_ty, event_type_fn_impl);
match event_kind {
Some(kind) => {
let i = kind.to_event_type_enum();
event_type_ty_decl = None;
event_type_ty = quote! { #ruma_common::events::#i };
event_type_fn_impl = match event_type.value().strip_suffix(".*") {
Some(type_prefix) => {
let type_suffix_data = event_type
.value()
.strip_suffix('*')
.map(|type_prefix| {
let type_fragment_field = fields
.find_map(|f| {
f.attrs.iter().filter(|a| a.path.is_ident("ruma_event")).find_map(|a| {
@ -500,9 +497,7 @@ fn generate_event_content_impl<'a>(
}
})
})
.transpose()?;
let f = type_fragment_field
.transpose()?
.ok_or_else(|| {
syn::Error::new_spanned(
event_type,
@ -514,10 +509,21 @@ fn generate_event_content_impl<'a>(
.as_ref()
.expect("type fragment field needs to have a name");
let format = type_prefix.to_owned() + ".{}";
<syn::Result<_>>::Ok((type_prefix.to_owned(), type_fragment_field))
})
.transpose()?;
match event_kind {
Some(kind) => {
let i = kind.to_event_type_enum();
event_type_ty_decl = None;
event_type_ty = quote! { #ruma_common::events::#i };
event_type_fn_impl = match &type_suffix_data {
Some((type_prefix, type_fragment_field)) => {
let format = type_prefix.to_owned() + "{}";
quote! {
::std::convert::From::from(::std::format!(#format, self.#f))
::std::convert::From::from(::std::format!(#format, self.#type_fragment_field))
}
}
None => quote! { ::std::convert::From::from(#event_type) },
@ -559,6 +565,31 @@ fn generate_event_content_impl<'a>(
}
});
let from_parts_fn_impl = if let Some((type_prefix, type_fragment_field)) = &type_suffix_data {
quote! {
if let Some(type_fragment) = ev_type.strip_prefix(#type_prefix) {
let mut content: Self = #serde_json::from_str(content.get())?;
content.#type_fragment_field = type_fragment.to_owned();
::std::result::Result::Ok(content)
} else {
::std::result::Result::Err(#serde::de::Error::custom(
::std::format!("expected event type starting with `{}`, found `{}`", #type_prefix, ev_type)
))
}
}
} else {
quote! {
if ev_type != #event_type {
return ::std::result::Result::Err(#serde::de::Error::custom(
::std::format!("expected event type `{}`, found `{}`", #event_type, ev_type)
));
}
#serde_json::from_str(content.get())
}
};
Ok(quote! {
#event_type_ty_decl
@ -574,13 +605,7 @@ fn generate_event_content_impl<'a>(
ev_type: &::std::primitive::str,
content: &#serde_json::value::RawValue,
) -> #serde_json::Result<Self> {
if ev_type != #event_type {
return ::std::result::Result::Err(#serde::de::Error::custom(
::std::format!("expected event type `{}`, found `{}`", #event_type, ev_type)
));
}
#serde_json::from_str(content.get())
#from_parts_fn_impl
}
}

View File

@ -131,7 +131,7 @@ fn generate_enum(
let ev_type = &e.ev_type;
Ok(if let Some(prefix) = ev_type.value().strip_suffix(".*") {
let fstr = prefix.to_owned() + "{}";
let fstr = prefix.to_owned() + ".{}";
quote! { #start(_s) => ::std::borrow::Cow::Owned(::std::format!(#fstr, _s)) }
} else {
quote! { #start => ::std::borrow::Cow::Borrowed(#ev_type) }