Macro event_enum

Source
event_enum!() { /* proc-macro */ }
Expand description

Generates enums to represent the various Matrix event types.

§Generated types

This generates the following enums for each kind:

  • Any{Kind}EventContent
  • Any{Kind}Event
  • {Kind}EventType

It also generates the following enums:

  • AnySync{Kind}Event for the kinds that have a different format in the /sync API: EphemeralRoom, MessageLike and State.
  • TimelineEventType which includes the variants from MessageLikeEventType and StateEventType
  • And extra enums for the State kind:
    • AnyInitialStateEvent for state events sent during room creation.
    • AnyStrippedStateEvent for state events that are in room state previews when receiving invites.
    • AnyFullStateEventContent a helper type to be able to access the content and prev_content of a state event.

This macro also implements the following traits for these enums, where it makes sense:

  • Serialize
  • Deserialize or EventContentFromType
  • {Kind}EventContent
  • Conversion from event type to enum variant, like:
    • From<{event_content_type}> for Any{Kind}EventContent
    • From<{event_type}> for Any{Kind}Event`

By default, the enums generated by this macro get a #[non_exhaustive] attribute. This behavior can be controlled by setting the ruma_unstable_exhaustive_types compile-time cfg setting as --cfg=ruma_unstable_exhaustive_types using RUSTFLAGS or .cargo/config.toml (under [build] -> rustflags = ["..."]). When that setting is activated, the attribute is not applied so the types are exhaustive.

§Syntax

The basic syntax for using this macro is:

event_enum! {
    enum Kind {
        "m.first_event_type" => path::to::first_event,
        "m.second_event_type" => path::to::second_event,
    }

    // …
}

§Enum Kind

The kind must be one of these values, which matches the EventContent macro:

  • MessageLike - A message-like event sent in the timeline
  • State - A state event sent in the timeline
  • GlobalAccountData - Global config event
  • RoomAccountData - Per-room config event
  • ToDevice - Event sent directly to a device
  • EphemeralRoom - Event that is not persistent in the room

§Event types

The first part of the event type declaration, before the arrow, is the string matching the type of the event, as defined in the Matrix specification. It must match the type attribute of the EventContent definition. Account data event types can end with .* in case the end of the event type changes dynamically, see the docs of EventContent for more details.

This type is used by the enums to know which variant to deserialize according to the type that can be found in the JSON data.

This macro supports deserialization from a second event type string with the alias attribute, which can be useful to support deserializing an event using both its stable and unstable prefixes, like this:

event_enum! {
    enum MessageLike {
        #[ruma_enum(alias = "dev.ruma.unstable.foo")]
        "m.foo" => path::to::foo,
    }
}

By default, this macro tries to generate the event types names from the event type string. It only recognizes strings that start with the m. prefix, which matches stable event types from the Matrix specification. From there it generates a base name by capitalizing every word, assuming that words are separated by . or _. For example, m.foo.bar will have the base name FooBar.

If the base name is incorrect, or the event type string uses an unstable prefix, the base name can be provided with the ident attribute, for example:

event_enum! {
    enum MessageLike {
        #[ruma_enum(ident = FooBar)]
        "dev.ruma.foo_bar" => path::to::foo_bar,
    }
}

The second part of the event type declaration, after the arrow, is the path of the module where the event types can be found.

This macro will then assume that all the necessary types are available in the given module to generate the code for the enums, as if the EventContent macro was used on a type named {base_name}EventContent.

You can use cargo doc to find out more details, its --document-private-items flag also lets you generate documentation for binaries or private parts of a library.

§Example

use ruma_macros::event_enum;

event_enum! {
    enum ToDevice {
        "m.any.event" => super::any_event,
        #[ruma_enum(alias = "dev.unstable.prefix.other.event")]
        "m.other.event" => super::other_event,
        #[cfg(feature = "unstable-mscXXXX")]
        #[ruma_enum(ident = NewEventEventContent)]
        "org.matrix.mscXXXX.new_event" => super::new_event,
    }

    enum State {
        "m.more.events" => super::more_events,
        "m.different.event" => super::different_event,
    }
}