Skip to main content

livekit_common/
enum_dispatch.rs

1// Copyright 2026 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/// Generates methods on an enum that forward each call to the inner value of every variant.
16///
17/// Given a list of variants and a set of method signatures, this expands to a `match` over `self`
18/// that dispatches to the identically-named method on each variant's inner type, saving the
19/// boilerplate of writing one `match` arm per variant per method.
20///
21/// ```ignore
22/// impl AnyStreamInfo {
23///     enum_dispatch!(
24///         [Byte, Text];
25///         pub fn id(self: &Self) -> &str;
26///         pub fn total_length(self: &Self) -> Option<u64>;
27///     );
28/// }
29/// ```
30// TODO(theomonnom): Async methods
31#[macro_export]
32macro_rules! enum_dispatch {
33    // This arm is used to avoid nested loops with the arguments
34    // The arguments are transformed to $combined_args tt
35    (@match [$($variant:ident),+]: $fnc:ident, $self:ident, $combined_args:tt) => {
36        match $self {
37            $(
38                Self::$variant(inner) => inner.$fnc$combined_args,
39            )+
40        }
41    };
42
43    // Create the function and extract self fron the $args tt (little hack)
44    (@fnc [$($variant:ident),+]: $vis:vis fn $fnc:ident($self:ident: $sty:ty $(, $arg:ident: $t:ty)*) -> $ret:ty) => {
45        #[inline]
46        $vis fn $fnc($self: $sty, $($arg: $t),*) -> $ret {
47            $crate::enum_dispatch!(@match [$($variant),+]: $fnc, $self, ($($arg,)*))
48        }
49    };
50
51    ($variants:tt; $($vis:vis fn $fnc:ident$args:tt -> $ret:ty;)+) => {
52        $(
53            $crate::enum_dispatch!(@fnc $variants: $vis fn $fnc$args -> $ret);
54        )+
55    };
56}