use core::convert::Infallible as Never;
use derivative::Derivative;
use log::trace;
use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6};
use netstack3_base::{CoreTimerContext, HandleableTimer, TimerHandler};
use netstack3_device::{DeviceLayerTimerId, WeakDeviceId};
use netstack3_ip::device::{IpDeviceIpExt, IpDeviceTimerId};
use netstack3_ip::IpLayerTimerId;
use crate::context::CoreCtx;
use crate::ip::integration::IpAddrCtxSpec;
use crate::transport::TransportLayerTimerId;
use crate::BindingsTypes;
pub use netstack3_base::{AtomicInstant, Instant};
#[derive(Derivative, GenericOverIp)]
#[derivative(
Clone(bound = ""),
Eq(bound = ""),
PartialEq(bound = ""),
Hash(bound = ""),
Debug(bound = "")
)]
#[generic_over_ip()]
pub struct TimerId<BT: BindingsTypes>(pub(crate) TimerIdInner<BT>);
#[derive(Derivative, GenericOverIp)]
#[derivative(
Clone(bound = ""),
Eq(bound = ""),
PartialEq(bound = ""),
Hash(bound = ""),
Debug(bound = "")
)]
#[generic_over_ip()]
pub enum TimerIdInner<BT: BindingsTypes> {
DeviceLayer(DeviceLayerTimerId<BT>),
TransportLayer(TransportLayerTimerId<BT>),
IpLayer(IpLayerTimerId),
Ipv4Device(IpDeviceTimerId<Ipv4, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>),
Ipv6Device(IpDeviceTimerId<Ipv6, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>),
}
impl<BT: BindingsTypes> From<DeviceLayerTimerId<BT>> for TimerId<BT> {
fn from(id: DeviceLayerTimerId<BT>) -> TimerId<BT> {
TimerId(TimerIdInner::DeviceLayer(id))
}
}
impl<BT: BindingsTypes> From<IpLayerTimerId> for TimerId<BT> {
fn from(id: IpLayerTimerId) -> TimerId<BT> {
TimerId(TimerIdInner::IpLayer(id))
}
}
impl<BT: BindingsTypes> From<TransportLayerTimerId<BT>> for TimerId<BT> {
fn from(id: TransportLayerTimerId<BT>) -> Self {
TimerId(TimerIdInner::TransportLayer(id))
}
}
impl<BT: BindingsTypes, I: IpDeviceIpExt>
From<IpDeviceTimerId<I, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>> for TimerId<BT>
{
fn from(value: IpDeviceTimerId<I, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>) -> Self {
I::map_ip(
value,
|v4| TimerId(TimerIdInner::Ipv4Device(v4)),
|v6| TimerId(TimerIdInner::Ipv6Device(v6)),
)
}
}
impl<CC, BT> HandleableTimer<CC, BT> for TimerId<BT>
where
BT: BindingsTypes,
CC: TimerHandler<BT, DeviceLayerTimerId<BT>>
+ TimerHandler<BT, TransportLayerTimerId<BT>>
+ TimerHandler<BT, IpLayerTimerId>
+ TimerHandler<BT, IpDeviceTimerId<Ipv4, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>>
+ TimerHandler<BT, IpDeviceTimerId<Ipv6, WeakDeviceId<BT>, IpAddrCtxSpec<BT>>>,
{
fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BT, timer: BT::UniqueTimerId) {
trace!("handle_timer: dispatching timerid: {self:?}");
match self {
TimerId(TimerIdInner::DeviceLayer(x)) => core_ctx.handle_timer(bindings_ctx, x, timer),
TimerId(TimerIdInner::TransportLayer(x)) => {
core_ctx.handle_timer(bindings_ctx, x, timer)
}
TimerId(TimerIdInner::IpLayer(x)) => core_ctx.handle_timer(bindings_ctx, x, timer),
TimerId(TimerIdInner::Ipv4Device(x)) => core_ctx.handle_timer(bindings_ctx, x, timer),
TimerId(TimerIdInner::Ipv6Device(x)) => core_ctx.handle_timer(bindings_ctx, x, timer),
}
}
}
impl<'a, BT, L> CoreTimerContext<Never, BT> for CoreCtx<'a, BT, L>
where
BT: BindingsTypes,
{
fn convert_timer(dispatch_id: Never) -> <BT as netstack3_base::TimerBindingsTypes>::DispatchId {
match dispatch_id {}
}
}