use std::{
iter::FromIterator,
mem::MaybeUninit,
task::{Context, Poll},
};
use super::SignalKind;
#[cfg(not(unix))]
use super::libc_polyfill as libc;
#[derive(Debug)]
pub struct SignalSet {
_private: (),
}
impl SignalSet {
#[inline]
pub fn builder() -> SignalSetBuilder {
SignalSetBuilder::new()
}
#[inline]
pub async fn recv(&mut self) -> Option<SignalKind> {
crate::util::poll_fn(|cx| self.poll_recv(cx)).await
}
pub fn poll_recv(
&mut self,
_cx: &mut Context<'_>,
) -> Poll<Option<SignalKind>> {
unimplemented!()
}
}
cfg_stream! {
impl futures::stream::Stream for SignalSet {
type Item = SignalKind;
#[inline]
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut Context<'_>
) -> Poll<Option<SignalKind>> {
self.poll_recv(cx)
}
}
}
#[derive(Clone, Copy)]
pub struct SignalSetBuilder {
signal_set: libc::sigset_t,
}
impl FromIterator<SignalKind> for SignalSetBuilder {
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = SignalKind>,
{
iter.into_iter()
.fold(Self::new(), |builder, signal| builder.with(signal))
}
}
impl Extend<SignalKind> for SignalSetBuilder {
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = SignalKind>,
{
iter.into_iter().for_each(|signal| self.insert(signal));
}
}
impl Default for SignalSetBuilder {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl SignalSetBuilder {
#[inline]
#[must_use]
pub fn new() -> Self {
unsafe {
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
libc::sigemptyset(set.as_mut_ptr());
Self::from_raw(set.assume_init())
}
}
#[inline]
#[must_use]
pub const unsafe fn from_raw(signal_set: libc::sigset_t) -> Self {
Self { signal_set }
}
#[inline]
#[must_use]
pub const fn into_raw(self) -> libc::sigset_t {
self.signal_set
}
#[inline]
#[must_use]
pub fn termination_set(self) -> Self {
self.alarm()
.hangup()
.interrupt()
.pipe()
.quit()
.terminate()
.user_defined_1()
.user_defined_2()
}
#[inline]
#[must_use]
pub fn alarm(self) -> Self {
self.with(SignalKind::ALARM)
}
#[inline]
#[must_use]
pub fn child(self) -> Self {
self.with(SignalKind::CHILD)
}
#[inline]
#[must_use]
pub fn hangup(self) -> Self {
self.with(SignalKind::HANGUP)
}
#[cfg(any(
not(any(
target_os = "android",
target_os = "emscripten",
target_os = "linux",
)),
docsrs,
))]
#[cfg_attr(
docsrs,
doc(not(any(
target_os = "android",
target_os = "emscripten",
target_os = "linux",
)))
)]
#[inline]
#[must_use]
pub fn info(self) -> Self {
self.with(SignalKind::INFO)
}
#[inline]
#[must_use]
pub fn interrupt(self) -> Self {
self.with(SignalKind::INTERRUPT)
}
#[inline]
#[must_use]
pub fn io(self) -> Self {
self.with(SignalKind::IO)
}
#[inline]
#[must_use]
pub fn pipe(self) -> Self {
self.with(SignalKind::PIPE)
}
#[inline]
#[must_use]
pub fn quit(self) -> Self {
self.with(SignalKind::QUIT)
}
#[inline]
#[must_use]
pub fn terminate(self) -> Self {
self.with(SignalKind::TERMINATE)
}
#[inline]
#[must_use]
pub fn user_defined_1(self) -> Self {
self.with(SignalKind::USER_DEFINED_1)
}
#[inline]
#[must_use]
pub fn user_defined_2(self) -> Self {
self.with(SignalKind::USER_DEFINED_2)
}
#[inline]
#[must_use]
pub fn window_change(self) -> Self {
self.with(SignalKind::WINDOW_CHANGE)
}
#[inline]
#[must_use]
pub fn with(mut self, signal: SignalKind) -> Self {
self.insert(signal);
self
}
#[inline]
pub fn insert(&mut self, signal: SignalKind) {
unsafe {
libc::sigaddset(&mut self.signal_set, signal.into_raw());
}
}
}