// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Macros used in Netstack3.

/// Implement [`TimerContext`] for one ID type in terms of an existing
/// implementation for a different ID type.
///
/// `$outer_timer_id` is an enum where one variant contains an
/// `$inner_timer_id`. `impl_timer_context!` generates an impl of
/// `TimerContext<$inner_timer_id>` for any `C: TimerContext<$outer_timer_id>`.
///
/// An impl of `Into<$outer_timer_id> for `$inner_timer_id` must exist. `$pat`
/// is a pattern of type `$outer_timer_id` that binds the `$inner_timer_id`.
/// `$bound_variable` is the name of the bound `$inner_timer_id` from the
/// pattern. For example, if `$pat` is `OuterTimerId::Inner(id)`, then
/// `$bound_variable` would be `id`. This is required for macro hygiene.
///
/// If an extra first parameter, `$bound`, is provided, then it is added as an
/// extra bound on the `C` context type.
///
/// [`TimerContext`]: crate::context::TimerContext
macro_rules! impl_timer_context {
    ($outer_timer_id:ty, $inner_timer_id:ty, $pat:pat, $bound_variable:ident) => {
        impl<C: crate::context::TimerContext<$outer_timer_id>>
            crate::context::TimerContext<$inner_timer_id> for C
        {
            impl_timer_context!(@inner $outer_timer_id, $inner_timer_id, $pat, $bound_variable);
        }
    };
    ($c_type:ident: $c_bound:ident, $outer_timer_id:ty, $inner_timer_id:ty, $pat:pat, $bound_variable:ident) => {
        impl<$c_type: $c_bound + crate::context::TimerContext<$outer_timer_id>>
            crate::context::TimerContext<$inner_timer_id> for $c_type
        {
            impl_timer_context!(@inner $outer_timer_id, $inner_timer_id, $pat, $bound_variable);
        }
    };
    ($other_type_arg:ident, $outer_timer_id:ty, $inner_timer_id:ty, $pat:pat, $bound_variable:ident) => {
        impl<$other_type_arg, C: crate::context::TimerContext<$outer_timer_id>>
            crate::context::TimerContext<$inner_timer_id> for C
        {
            impl_timer_context!(@inner $outer_timer_id, $inner_timer_id, $pat, $bound_variable);
        }
    };
    ($other_type_arg:ident: $o_bound:path, $outer_timer_id:ty, $inner_timer_id:ty, $pat:pat, $bound_variable:ident) => {
        impl<$other_type_arg: $o_bound, C: crate::context::TimerContext<$outer_timer_id>>
            crate::context::TimerContext<$inner_timer_id> for C
        {
            impl_timer_context!(@inner $outer_timer_id, $inner_timer_id, $pat, $bound_variable);
        }
    };
    (@inner $outer_timer_id:ty, $inner_timer_id:ty, $pat:pat, $bound_variable:ident) => {
        fn schedule_timer_instant(
            &mut self,
            time: Self::Instant,
            id: $inner_timer_id,
        ) -> Option<Self::Instant> {
            crate::context::TimerContext::<$outer_timer_id>::schedule_timer_instant(self, time, id.into())
        }

        fn cancel_timer(&mut self, id: $inner_timer_id) -> Option<Self::Instant> {
            crate::context::TimerContext::<$outer_timer_id>::cancel_timer(self, id.into())
        }

        fn cancel_timers_with<F: FnMut(&$inner_timer_id) -> bool>(&mut self, mut f: F) {
            crate::context::TimerContext::<$outer_timer_id>::cancel_timers_with(self, |id| match id {
                $pat => f($bound_variable),
                #[allow(unreachable_patterns)]
                _ => false,
            })
        }

        fn scheduled_instant(&self, id: $inner_timer_id) -> Option<Self::Instant> {
            crate::context::TimerContext::<$outer_timer_id>::scheduled_instant(self, id.into())
        }
    };
}

/// Declare a benchmark function.
///
/// The function will be named `$name`. If the `benchmark` cfg is enabled, the
/// provided `$fn` will be invoked with a `&mut criterion::Bencher` - in other
/// words, a real benchmark. If the `benchmark` cfg is disabled, the function
/// will be annotated with the `#[test]` attribute, and the provided `$fn` will
/// be invoked with a `&mut TestBencher`, which has the effect of creating a
/// test that runs the benchmarked function for a small, fixed number of
/// iterations. This test allows the use of debug assertions to verify the
/// correctness of the benchmark.
///
/// Note that `$fn` doesn't have to be a named function - it can also be an
/// anonymous closure.
#[cfg(test)]
macro_rules! bench {
    ($name:ident, $fn:expr) => {
        #[cfg(benchmark)]
        fn $name(b: &mut criterion::Bencher) {
            $fn(b);
        }

        #[cfg(not(benchmark))]
        #[test]
        fn $name() {
            $fn(&mut crate::testutil::benchmarks::TestBencher);
        }
    };
}
