I have the event system, that allows subscribing to events using paths. And I've made the macro to create such paths in a less verbose way. That's fine. But I want to use the same macro for pattern matching.
path!("object", 10)
will expand to
[PathElement::from("object"), PathElement::from(10)]
But for pattern matching I need
path!("object", object_id)
to expand to
[PathElement::String("object"), PathElement::int(object_id)]
so that it can be used as a match pattern.
Full code:
playground
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum PathElement {
Any, // match any path element
Rest, // match any remaining path elements
Int(i32),
String(&'static str),
}
impl From<&'static str> for PathElement {
fn from(value: &'static str) -> Self {
Self::String(value)
}
}
impl From<i32> for PathElement {
fn from(value: i32) -> Self {
Self::Int(value)
}
}
macro_rules! path_element {
(*) => {
crate::PathElement::Any
};
($element:literal) => {
crate::PathElement::from($element)
};
}
macro_rules! path {
($($element:tt), + ..) => {{
[
$(
path_element!($element),
)+
PathElement::Rest,
]
}};
($($element:tt), +) => (
[
$(
path_element!($element),
)+
]
);
}
fn main() {
let path = &path!("object", *, "action", * ..)[..];
assert_eq!(path, [
PathElement::String("object"),
PathElement::Any,
PathElement::String("action"),
PathElement::Any,
PathElement::Rest,
]);
let path = &path!("object", 10, "action", 15)[..];
match path {
// I would like this to be
// `path!("object", object_id, "action", action_id) => {...}`
[crate::PathElement::String("object"), crate::PathElement::Int(object_id), crate::PathElement::String("action"), crate::PathElement::Int(action_id)] =>
{
assert_eq!(object_id, &10);
assert_eq!(action_id, &15);
}
_ => {
panic!("not matched");
}
}
println!("ok");
}