macros: Finish support for variable event types
This commit is contained in:
parent
316d1423e8
commit
7fbb28f223
@ -86,8 +86,8 @@ pub mod v3 {
|
|||||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||||
|
|
||||||
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
||||||
let event_type_percent =
|
let event_type = self.event_type.to_string();
|
||||||
utf8_percent_encode(self.event_type.as_str(), NON_ALPHANUMERIC);
|
let event_type_percent = utf8_percent_encode(&event_type, NON_ALPHANUMERIC);
|
||||||
|
|
||||||
let mut url = format!(
|
let mut url = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -114,8 +114,8 @@ pub mod v3 {
|
|||||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||||
|
|
||||||
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
||||||
let event_type_percent =
|
let event_type = self.event_type.to_string();
|
||||||
utf8_percent_encode(self.event_type.as_str(), NON_ALPHANUMERIC);
|
let event_type_percent = utf8_percent_encode(&event_type, NON_ALPHANUMERIC);
|
||||||
|
|
||||||
let mut url = format!(
|
let mut url = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -306,7 +306,7 @@ fn alias_event_field_access() {
|
|||||||
} else {
|
} else {
|
||||||
panic!("the `Any*Event` enum's accessor methods may have been altered")
|
panic!("the `Any*Event` enum's accessor methods may have been altered")
|
||||||
}
|
}
|
||||||
assert_eq!(deser.event_type().as_str(), "m.room.aliases");
|
assert_eq!(deser.event_type().to_string(), "m.room.aliases");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -12,7 +12,7 @@ fn main() {
|
|||||||
use ruma_common::events::EventContent;
|
use ruma_common::events::EventContent;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MacroTestContent { frag: "foo".to_owned() }.event_type().as_str(),
|
MacroTestContent { frag: "foo".to_owned() }.event_type().to_string(),
|
||||||
"m.macro.test.foo"
|
"m.macro.test.foo"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -119,14 +119,13 @@ fn expand_serialize_event(
|
|||||||
{
|
{
|
||||||
use #serde::ser::{SerializeStruct as _, Error as _};
|
use #serde::ser::{SerializeStruct as _, Error as _};
|
||||||
|
|
||||||
let event_type = #ruma_common::events::EventContent::event_type(&self.content);
|
|
||||||
let event_type =
|
|
||||||
::std::convert::AsRef::<::std::primitive::str>::as_ref(&event_type);
|
|
||||||
|
|
||||||
let mut state = serializer.serialize_struct(stringify!(#ident), 7)?;
|
let mut state = serializer.serialize_struct(stringify!(#ident), 7)?;
|
||||||
|
|
||||||
state.serialize_field("type", event_type)?;
|
let event_type = #ruma_common::events::EventContent::event_type(&self.content);
|
||||||
|
state.serialize_field("type", &event_type)?;
|
||||||
|
|
||||||
#( #serialize_fields )*
|
#( #serialize_fields )*
|
||||||
|
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,9 +474,13 @@ fn generate_event_content_impl<'a>(
|
|||||||
ty: ::std::option::Option<crate::PrivOwnedStr>,
|
ty: ::std::option::Option<crate::PrivOwnedStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::convert::AsRef<::std::primitive::str> for #i {
|
impl #serde::Serialize for #i {
|
||||||
fn as_ref(&self) -> &::std::primitive::str {
|
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
|
||||||
self.ty.as_ref().map(|t| &t.0[..]).unwrap_or(#event_type)
|
where
|
||||||
|
S: #serde::Serializer,
|
||||||
|
{
|
||||||
|
let s = self.ty.as_ref().map(|t| &t.0[..]).unwrap_or(#event_type);
|
||||||
|
serializer.serialize_str(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -240,7 +240,7 @@ fn expand_into_full_event(
|
|||||||
/// Create a content enum from `EventEnumInput`.
|
/// Create a content enum from `EventEnumInput`.
|
||||||
fn expand_content_enum(
|
fn expand_content_enum(
|
||||||
kind: EventKind,
|
kind: EventKind,
|
||||||
events: &[LitStr],
|
event_types: &[LitStr],
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
variants: &[EventEnumVariant],
|
variants: &[EventEnumVariant],
|
||||||
ruma_common: &TokenStream,
|
ruma_common: &TokenStream,
|
||||||
@ -251,13 +251,18 @@ fn expand_content_enum(
|
|||||||
let ident = kind.to_content_enum();
|
let ident = kind.to_content_enum();
|
||||||
|
|
||||||
let event_type_enum = kind.to_event_type_enum();
|
let event_type_enum = kind.to_event_type_enum();
|
||||||
let event_type_str = events;
|
|
||||||
|
|
||||||
let content: Vec<_> =
|
let content: Vec<_> =
|
||||||
events.iter().map(|ev| to_event_content_path(kind, ev, None, ruma_common)).collect();
|
event_types.iter().map(|ev| to_event_content_path(kind, ev, None, ruma_common)).collect();
|
||||||
|
let event_type_match_arms = event_types.iter().map(|s| {
|
||||||
|
if let Some(prefix) = s.value().strip_suffix(".*") {
|
||||||
|
quote! { _s if _s.starts_with(#prefix) }
|
||||||
|
} else {
|
||||||
|
quote! { #s }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
||||||
|
|
||||||
let variant_attrs = variants.iter().map(|v| {
|
let variant_attrs = variants.iter().map(|v| {
|
||||||
let attrs = &v.attrs;
|
let attrs = &v.attrs;
|
||||||
quote! { #(#attrs)* }
|
quote! { #(#attrs)* }
|
||||||
@ -278,7 +283,7 @@ fn expand_content_enum(
|
|||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
pub enum #ident {
|
pub enum #ident {
|
||||||
#(
|
#(
|
||||||
#[doc = #event_type_str]
|
#[doc = #event_types]
|
||||||
#variant_decls(#content),
|
#variant_decls(#content),
|
||||||
)*
|
)*
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -305,7 +310,7 @@ fn expand_content_enum(
|
|||||||
) -> #serde_json::Result<Self> {
|
) -> #serde_json::Result<Self> {
|
||||||
match event_type {
|
match event_type {
|
||||||
#(
|
#(
|
||||||
#variant_attrs #event_type_str => {
|
#variant_attrs #event_type_match_arms => {
|
||||||
let content = #content::from_parts(event_type, input)?;
|
let content = #content::from_parts(event_type, input)?;
|
||||||
::std::result::Result::Ok(#variant_ctors(content))
|
::std::result::Result::Ok(#variant_ctors(content))
|
||||||
}
|
}
|
||||||
@ -434,7 +439,9 @@ fn expand_accessor_methods(
|
|||||||
event.unsigned._map_prev_unsigned(|c| #content_enum::_Custom {
|
event.unsigned._map_prev_unsigned(|c| #content_enum::_Custom {
|
||||||
event_type: crate::PrivOwnedStr(
|
event_type: crate::PrivOwnedStr(
|
||||||
::std::convert::From::from(
|
::std::convert::From::from(
|
||||||
#ruma_common::events::EventContent::event_type(c).as_str()
|
::std::string::ToString::to_string(
|
||||||
|
&#ruma_common::events::EventContent::event_type(c)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@ -467,8 +474,9 @@ fn expand_accessor_methods(
|
|||||||
Self::_Custom(event) => #content_enum::_Custom {
|
Self::_Custom(event) => #content_enum::_Custom {
|
||||||
event_type: crate::PrivOwnedStr(
|
event_type: crate::PrivOwnedStr(
|
||||||
::std::convert::From::from(
|
::std::convert::From::from(
|
||||||
#ruma_common::events::EventContent::event_type(&event.content)
|
::std::string::ToString::to_string(
|
||||||
.as_str(),
|
&#ruma_common::events::EventContent::event_type(&event.content)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -627,9 +635,14 @@ impl EventEnumVariant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EventEnumEntry {
|
impl EventEnumEntry {
|
||||||
|
pub(crate) fn has_type_fragment(&self) -> bool {
|
||||||
|
self.ev_type.value().ends_with(".*")
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn to_variant(&self) -> syn::Result<EventEnumVariant> {
|
pub(crate) fn to_variant(&self) -> syn::Result<EventEnumVariant> {
|
||||||
let attrs = self.attrs.clone();
|
let attrs = self.attrs.clone();
|
||||||
let ident = m_prefix_name_to_type_name(&self.ev_type)?;
|
let ident = m_prefix_name_to_type_name(&self.ev_type)?;
|
||||||
|
|
||||||
Ok(EventEnumVariant { attrs, ident })
|
Ok(EventEnumVariant { attrs, ident })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,7 @@ fn generate_enum(
|
|||||||
input: &[&Vec<EventEnumEntry>],
|
input: &[&Vec<EventEnumEntry>],
|
||||||
ruma_common: &TokenStream,
|
ruma_common: &TokenStream,
|
||||||
) -> syn::Result<TokenStream> {
|
) -> syn::Result<TokenStream> {
|
||||||
let str_doc = format!("Creates a string slice from this `{}`.", ident);
|
let serde = quote! { #ruma_common::exports::serde };
|
||||||
let byte_doc = format!("Creates a byte slice from this `{}`.", ident);
|
|
||||||
let enum_doc = format!("The type of `{}` this is.", ident.strip_suffix("Type").unwrap());
|
let enum_doc = format!("The type of `{}` this is.", ident.strip_suffix("Type").unwrap());
|
||||||
|
|
||||||
let deprecated_attr = (ident == "EventType").then(|| {
|
let deprecated_attr = (ident == "EventType").then(|| {
|
||||||
@ -86,8 +85,57 @@ fn generate_enum(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let event_types = deduped.iter().map(|e| &e.ev_type);
|
let event_types = deduped.iter().map(|e| &e.ev_type);
|
||||||
let variants =
|
|
||||||
deduped.iter().map(|e| Ok(e.to_variant()?.decl())).collect::<syn::Result<Vec<_>>>()?;
|
let variants: Vec<_> = deduped
|
||||||
|
.iter()
|
||||||
|
.map(|e| {
|
||||||
|
let start = e.to_variant()?.decl();
|
||||||
|
let data = e.has_type_fragment().then(|| quote! { (::std::string::String) });
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#start #data
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<syn::Result<_>>()?;
|
||||||
|
|
||||||
|
let to_cow_str_match_arms: Vec<_> = deduped
|
||||||
|
.iter()
|
||||||
|
.map(|e| {
|
||||||
|
let v = e.to_variant()?;
|
||||||
|
let start = v.match_arm(quote! { Self });
|
||||||
|
let ev_type = &e.ev_type;
|
||||||
|
|
||||||
|
Ok(if let Some(prefix) = ev_type.value().strip_suffix(".*") {
|
||||||
|
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) }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<syn::Result<_>>()?;
|
||||||
|
|
||||||
|
let from_str_match_arms: Vec<_> = deduped
|
||||||
|
.iter()
|
||||||
|
.map(|e| {
|
||||||
|
let v = e.to_variant()?;
|
||||||
|
let ctor = v.ctor(quote! { Self });
|
||||||
|
|
||||||
|
let match_arm = if let Some(prefix) = e.ev_type.value().strip_suffix('*') {
|
||||||
|
quote! {
|
||||||
|
// Use if-let guard once available
|
||||||
|
_s if _s.starts_with(#prefix) => {
|
||||||
|
#ctor(::std::convert::From::from(_s.strip_prefix(#prefix).unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let t = &e.ev_type;
|
||||||
|
quote! { #t => #ctor }
|
||||||
|
};
|
||||||
|
|
||||||
|
let attrs = &e.attrs;
|
||||||
|
Ok(quote! { #(#attrs)* #match_arm })
|
||||||
|
})
|
||||||
|
.collect::<syn::Result<_>>()?;
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[doc = #enum_doc]
|
#[doc = #enum_doc]
|
||||||
@ -95,12 +143,11 @@ fn generate_enum(
|
|||||||
/// This type can hold an arbitrary string. To check for events that are not available as a
|
/// This type can hold an arbitrary string. To check for events that are not available as a
|
||||||
/// documented variant here, use its string representation, obtained through `.as_str()`.
|
/// documented variant here, use its string representation, obtained through `.as_str()`.
|
||||||
#deprecated_attr
|
#deprecated_attr
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, #ruma_common::serde::StringEnum)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
pub enum #ident {
|
pub enum #ident {
|
||||||
#(
|
#(
|
||||||
#[doc = #event_types]
|
#[doc = #event_types]
|
||||||
#[ruma_enum(rename = #event_types)]
|
|
||||||
#variants,
|
#variants,
|
||||||
)*
|
)*
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -109,14 +156,56 @@ fn generate_enum(
|
|||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl #ident {
|
impl #ident {
|
||||||
#[doc = #str_doc]
|
fn to_cow_str(&self) -> ::std::borrow::Cow<'_, ::std::primitive::str> {
|
||||||
pub fn as_str(&self) -> &str {
|
match self {
|
||||||
self.as_ref()
|
#(#to_cow_str_match_arms,)*
|
||||||
|
Self::_Custom(crate::PrivOwnedStr(s)) => ::std::borrow::Cow::Borrowed(s),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[doc = #byte_doc]
|
#[allow(deprecated)]
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
impl ::std::fmt::Display for #ident {
|
||||||
self.as_str().as_bytes()
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
self.to_cow_str().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl ::std::convert::From<&::std::primitive::str> for #ident {
|
||||||
|
fn from(s: &::std::primitive::str) -> Self {
|
||||||
|
match s {
|
||||||
|
#(#from_str_match_arms,)*
|
||||||
|
_ => Self::_Custom(crate::PrivOwnedStr(::std::convert::From::from(s))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl ::std::convert::From<::std::string::String> for #ident {
|
||||||
|
fn from(s: ::std::string::String) -> Self {
|
||||||
|
::std::convert::From::from(s.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl<'de> #serde::Deserialize<'de> for #ident {
|
||||||
|
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: #serde::Deserializer<'de>
|
||||||
|
{
|
||||||
|
let s = #ruma_common::serde::deserialize_cow_str(deserializer)?;
|
||||||
|
Ok(::std::convert::From::from(&s[..]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl #serde::Serialize for #ident {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: #serde::Serializer,
|
||||||
|
{
|
||||||
|
self.to_cow_str().serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user