use std::cell::Cell;
use std::marker::PhantomData;
use std::os::fd::{AsFd, BorrowedFd};
use crate::subscriber::{Handler, HasInterest};
use crate::{Event, EventpOps, Interest, Pinned};
pub struct TriSubscriber<Fd, Args, F> {
pub fd: Fd,
pub interest: Cell<Interest>,
pub handler: FnHandler<Args, F>,
}
pub struct FnHandler<Args, F> {
f: F,
_marker: PhantomData<fn(Args)>,
}
impl<Fd, Args, F> AsFd for TriSubscriber<Fd, Args, F>
where
Fd: AsFd,
{
fn as_fd(&self) -> BorrowedFd<'_> {
self.fd.as_fd()
}
}
impl<Fd, Args, F> HasInterest for TriSubscriber<Fd, Args, F> {
fn interest(&self) -> &Cell<Interest> {
&self.interest
}
}
impl Interest {
pub const fn with_fd<Fd: AsFd>(self, fd: Fd) -> (Self, Fd) {
(self, fd)
}
pub const fn with_handler<Args, F>(self, f: F) -> (Self, FnHandler<Args, F>) {
(
self,
FnHandler {
f,
_marker: PhantomData,
},
)
}
}
pub trait WithFd {
type Out<Fd>;
fn with_fd<Fd: AsFd>(self, fd: Fd) -> Self::Out<Fd>;
}
impl<Args, F> WithFd for (Interest, FnHandler<Args, F>) {
type Out<Fd> = TriSubscriber<Fd, Args, F>;
fn with_fd<Fd: AsFd>(self, fd: Fd) -> Self::Out<Fd> {
TriSubscriber {
fd,
interest: Cell::new(self.0),
handler: self.1,
}
}
}
pub trait WithHandler {
type Out<Args, F>;
fn with_handler<Args, F>(self, f: F) -> Self::Out<Args, F>;
}
impl<Fd: AsFd> WithHandler for (Interest, Fd) {
type Out<Args, F> = TriSubscriber<Fd, Args, F>;
fn with_handler<Args, F>(self, f: F) -> Self::Out<Args, F> {
TriSubscriber {
fd: self.1,
interest: Cell::new(self.0),
handler: FnHandler {
f,
_marker: PhantomData,
},
}
}
}
impl<Ep, Fd, F> Handler<Ep> for TriSubscriber<Fd, (), F>
where
Ep: EventpOps,
Fd: AsFd,
F: FnMut(),
{
fn handle(&mut self, _event: Event, _eventp: Pinned<'_, Ep>) {
(self.handler.f)()
}
}
macro_rules! expand_param_type {
(fd) => { &mut Fd };
(event) => { crate::Event };
(interest) => { crate::Interest };
(eventp) => { Pinned<'_, Ep> };
}
macro_rules! impl_handler {
(@build_call ($s:ident, $e:ident, $i:ident, $ep:ident) -> @args( $($processed:expr,)* ) fd, $($tail:ident,)*) => {
impl_handler!(@build_call ($s, $e, $i, $ep) -> @args( $($processed,)* &mut $s.fd, ) $($tail,)*)
};
(@build_call ($s:ident, $e:ident, $i:ident, $ep:ident) -> @args( $($processed:expr,)* ) event, $($tail:ident,)*) => {
impl_handler!(@build_call ($s, $e, $i, $ep) -> @args( $($processed,)* $e, ) $($tail,)*)
};
(@build_call ($s:ident, $e:ident, $i:ident, $ep:ident) -> @args( $($processed:expr,)* ) interest, $($tail:ident,)*) => {
impl_handler!(@build_call ($s, $e, $i, $ep) -> @args( $($processed,)* $i.interest.get(), ) $($tail,)*)
};
(@build_call ($s:ident, $e:ident, $i:ident, $ep:ident) -> @args( $($processed:expr,)* ) eventp, $($tail:ident,)*) => {
impl_handler!(@build_call ($s, $e, $i, $ep) -> @args( $($processed,)* $ep, ) $($tail,)*)
};
(@build_call ($s:ident, $e:ident, $i:ident, $ep:ident) -> @args( $($processed:expr,)* )) => {
($s.handler.f)($($processed),*)
};
( $( $param:ident ),+ ) => {
impl<Ep, Fd, F> Handler<Ep> for TriSubscriber<Fd, ( $( expand_param_type!($param), )* ), F>
where
Ep: EventpOps,
Fd: AsFd,
F: FnMut( $( expand_param_type!($param), )* ),
{
#[allow(unused_variables)]
fn handle(&mut self, event: Event, eventp: Pinned<'_, Ep>) {
impl_handler!(@build_call (self, event, self, eventp) -> @args() $($param,)*);
}
}
};
}
impl_handler!(fd);
impl_handler!(event);
impl_handler!(interest);
impl_handler!(eventp);
impl_handler!(fd, event);
impl_handler!(fd, interest);
impl_handler!(fd, eventp);
impl_handler!(event, fd);
impl_handler!(event, interest);
impl_handler!(event, eventp);
impl_handler!(interest, fd);
impl_handler!(interest, event);
impl_handler!(interest, eventp);
impl_handler!(eventp, fd);
impl_handler!(eventp, event);
impl_handler!(eventp, interest);
impl_handler!(fd, event, interest);
impl_handler!(fd, event, eventp);
impl_handler!(fd, interest, event);
impl_handler!(fd, interest, eventp);
impl_handler!(fd, eventp, event);
impl_handler!(fd, eventp, interest);
impl_handler!(event, fd, interest);
impl_handler!(event, fd, eventp);
impl_handler!(event, interest, fd);
impl_handler!(event, interest, eventp);
impl_handler!(event, eventp, fd);
impl_handler!(event, eventp, interest);
impl_handler!(interest, fd, event);
impl_handler!(interest, fd, eventp);
impl_handler!(interest, event, fd);
impl_handler!(interest, event, eventp);
impl_handler!(interest, eventp, fd);
impl_handler!(interest, eventp, event);
impl_handler!(eventp, fd, event);
impl_handler!(eventp, fd, interest);
impl_handler!(eventp, event, fd);
impl_handler!(eventp, event, interest);
impl_handler!(eventp, interest, fd);
impl_handler!(eventp, interest, event);
impl_handler!(fd, event, interest, eventp);
impl_handler!(fd, event, eventp, interest);
impl_handler!(fd, interest, event, eventp);
impl_handler!(fd, interest, eventp, event);
impl_handler!(fd, eventp, event, interest);
impl_handler!(fd, eventp, interest, event);
impl_handler!(event, fd, interest, eventp);
impl_handler!(event, fd, eventp, interest);
impl_handler!(event, interest, fd, eventp);
impl_handler!(event, interest, eventp, fd);
impl_handler!(event, eventp, fd, interest);
impl_handler!(event, eventp, interest, fd);
impl_handler!(interest, fd, event, eventp);
impl_handler!(interest, fd, eventp, event);
impl_handler!(interest, event, fd, eventp);
impl_handler!(interest, event, eventp, fd);
impl_handler!(interest, eventp, fd, event);
impl_handler!(interest, eventp, event, fd);
impl_handler!(eventp, fd, event, interest);
impl_handler!(eventp, fd, interest, event);
impl_handler!(eventp, event, fd, interest);
impl_handler!(eventp, event, interest, fd);
impl_handler!(eventp, interest, fd, event);
impl_handler!(eventp, interest, event, fd);