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};
|
||||
|
||||
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
||||
let event_type_percent =
|
||||
utf8_percent_encode(self.event_type.as_str(), NON_ALPHANUMERIC);
|
||||
let event_type = self.event_type.to_string();
|
||||
let event_type_percent = utf8_percent_encode(&event_type, NON_ALPHANUMERIC);
|
||||
|
||||
let mut url = format!(
|
||||
"{}{}",
|
||||
|
@ -114,8 +114,8 @@ pub mod v3 {
|
||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC);
|
||||
let event_type_percent =
|
||||
utf8_percent_encode(self.event_type.as_str(), NON_ALPHANUMERIC);
|
||||
let event_type = self.event_type.to_string();
|
||||
let event_type_percent = utf8_percent_encode(&event_type, NON_ALPHANUMERIC);
|
||||
|
||||
let mut url = format!(
|
||||
"{}{}",
|
||||
|
@ -306,7 +306,7 @@ fn alias_event_field_access() {
|
||||
} else {
|
||||
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]
|
||||
|
@ -12,7 +12,7 @@ fn main() {
|
||||
use ruma_common::events::EventContent;
|
||||
|
||||
assert_eq!(
|
||||
MacroTestContent { frag: "foo".to_owned() }.event_type().as_str(),
|
||||
MacroTestContent { frag: "foo".to_owned() }.event_type().to_string(),
|
||||
"m.macro.test.foo"
|
||||
);
|
||||
}
|
||||
|
@ -119,14 +119,13 @@ fn expand_serialize_event(
|
||||
{
|
||||
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)?;
|
||||
|
||||
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 )*
|
||||
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
@ -474,9 +474,13 @@ fn generate_event_content_impl<'a>(
|
||||
ty: ::std::option::Option<crate::PrivOwnedStr>,
|
||||
}
|
||||
|
||||
impl ::std::convert::AsRef<::std::primitive::str> for #i {
|
||||
fn as_ref(&self) -> &::std::primitive::str {
|
||||
self.ty.as_ref().map(|t| &t.0[..]).unwrap_or(#event_type)
|
||||
impl #serde::Serialize for #i {
|
||||
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
|
||||
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`.
|
||||
fn expand_content_enum(
|
||||
kind: EventKind,
|
||||
events: &[LitStr],
|
||||
event_types: &[LitStr],
|
||||
attrs: &[Attribute],
|
||||
variants: &[EventEnumVariant],
|
||||
ruma_common: &TokenStream,
|
||||
@ -251,13 +251,18 @@ fn expand_content_enum(
|
||||
let ident = kind.to_content_enum();
|
||||
|
||||
let event_type_enum = kind.to_event_type_enum();
|
||||
let event_type_str = events;
|
||||
|
||||
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_attrs = variants.iter().map(|v| {
|
||||
let attrs = &v.attrs;
|
||||
quote! { #(#attrs)* }
|
||||
@ -278,7 +283,7 @@ fn expand_content_enum(
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub enum #ident {
|
||||
#(
|
||||
#[doc = #event_type_str]
|
||||
#[doc = #event_types]
|
||||
#variant_decls(#content),
|
||||
)*
|
||||
#[doc(hidden)]
|
||||
@ -305,7 +310,7 @@ fn expand_content_enum(
|
||||
) -> #serde_json::Result<Self> {
|
||||
match event_type {
|
||||
#(
|
||||
#variant_attrs #event_type_str => {
|
||||
#variant_attrs #event_type_match_arms => {
|
||||
let content = #content::from_parts(event_type, input)?;
|
||||
::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_type: crate::PrivOwnedStr(
|
||||
::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 {
|
||||
event_type: crate::PrivOwnedStr(
|
||||
::std::convert::From::from(
|
||||
#ruma_common::events::EventContent::event_type(&event.content)
|
||||
.as_str(),
|
||||
::std::string::ToString::to_string(
|
||||
&#ruma_common::events::EventContent::event_type(&event.content)
|
||||
)
|
||||
),
|
||||
),
|
||||
},
|
||||
@ -627,9 +635,14 @@ impl EventEnumVariant {
|
||||
}
|
||||
|
||||
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> {
|
||||
let attrs = self.attrs.clone();
|
||||
let ident = m_prefix_name_to_type_name(&self.ev_type)?;
|
||||
|
||||
Ok(EventEnumVariant { attrs, ident })
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,7 @@ fn generate_enum(
|
||||
input: &[&Vec<EventEnumEntry>],
|
||||
ruma_common: &TokenStream,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let str_doc = format!("Creates a string slice from this `{}`.", ident);
|
||||
let byte_doc = format!("Creates a byte slice from this `{}`.", ident);
|
||||
let serde = quote! { #ruma_common::exports::serde };
|
||||
let enum_doc = format!("The type of `{}` this is.", ident.strip_suffix("Type").unwrap());
|
||||
|
||||
let deprecated_attr = (ident == "EventType").then(|| {
|
||||
@ -86,8 +85,57 @@ fn generate_enum(
|
||||
}
|
||||
|
||||
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! {
|
||||
#[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
|
||||
/// documented variant here, use its string representation, obtained through `.as_str()`.
|
||||
#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)]
|
||||
pub enum #ident {
|
||||
#(
|
||||
#[doc = #event_types]
|
||||
#[ruma_enum(rename = #event_types)]
|
||||
#variants,
|
||||
)*
|
||||
#[doc(hidden)]
|
||||
@ -109,14 +156,56 @@ fn generate_enum(
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl #ident {
|
||||
#[doc = #str_doc]
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.as_ref()
|
||||
fn to_cow_str(&self) -> ::std::borrow::Cow<'_, ::std::primitive::str> {
|
||||
match self {
|
||||
#(#to_cow_str_match_arms,)*
|
||||
Self::_Custom(crate::PrivOwnedStr(s)) => ::std::borrow::Cow::Borrowed(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = #byte_doc]
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.as_str().as_bytes()
|
||||
#[allow(deprecated)]
|
||||
impl ::std::fmt::Display for #ident {
|
||||
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