Skip to content

Commit

Permalink
Implement Extend and From/IntoIterator for SigSet
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant committed Oct 17, 2021
1 parent c5db0ea commit 97efade
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 8 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased] - ReleaseDate
### Added

- Implemented `Extend`, `FromIterator`, and `IntoIterator` for `SigSet` and
added `SigSet::iter` and `SigSetIter`.
(#[1553](https://github.com/nix-rust/nix/pull/1553))

### Changed

- Removed `SigSet::extend` in favor of `<SigSet as Extend<Signal>>::extend`.
Because of this change, you now need `use std::iter::Extend` to call `extend`
on a `SigSet`.
(#[1553](https://github.com/nix-rust/nix/pull/1553))

## [0.23.0] - 2021-09-28
### Added

Expand Down
70 changes: 62 additions & 8 deletions src/sys/signal.rs
Expand Up @@ -6,6 +6,9 @@
use crate::{Error, Result};
use crate::errno::Errno;
use crate::unistd::Pid;
use std::iter::Extend;
use std::iter::FromIterator;
use std::iter::IntoIterator;
use std::mem;
use std::fmt;
use std::str::FromStr;
Expand Down Expand Up @@ -500,14 +503,9 @@ impl SigSet {
}
}

/// Merge all of `other`'s signals into this set.
// TODO: use libc::sigorset on supported operating systems.
pub fn extend(&mut self, other: &SigSet) {
for signal in Signal::iterator() {
if other.contains(signal) {
self.add(signal);
}
}
/// Returns an iterator that yields the signals contained in this set.
pub fn iter(&self) -> SigSetIter<'_> {
self.into_iter()
}

/// Gets the currently blocked (masked) set of signals for the calling thread.
Expand Down Expand Up @@ -560,6 +558,55 @@ impl AsRef<libc::sigset_t> for SigSet {
}
}

// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
impl Extend<Signal> for SigSet {
fn extend<T>(&mut self, iter: T)
where T: IntoIterator<Item = Signal> {
for signal in iter {
self.add(signal);
}
}
}

impl FromIterator<Signal> for SigSet {
fn from_iter<T>(iter: T) -> Self
where T: IntoIterator<Item = Signal> {
let mut sigset = SigSet::empty();
sigset.extend(iter);
sigset
}
}

/// Iterator for a [`SigSet`].
///
/// Call [`SigSet::iter`] to create an iterator.
#[derive(Clone, Debug)]
pub struct SigSetIter<'a> {
sigset: &'a SigSet,
inner: SignalIterator,
}

impl Iterator for SigSetIter<'_> {
type Item = Signal;
fn next(&mut self) -> Option<Signal> {
loop {
match self.inner.next() {
None => return None,
Some(signal) if self.sigset.contains(signal) => return Some(signal),
Some(_signal) => continue,
}
}
}
}

impl<'a> IntoIterator for &'a SigSet {
type Item = Signal;
type IntoIter = SigSetIter<'a>;
fn into_iter(self) -> Self::IntoIter {
SigSetIter { sigset: self, inner: Signal::iterator() }
}
}

/// A signal handler.
#[allow(unknown_lints)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
Expand Down Expand Up @@ -1180,6 +1227,13 @@ mod tests {
}).join().unwrap();
}

#[test]
fn test_from_and_into_iterator() {
let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
let signals = sigset.into_iter().collect::<Vec<Signal>>();
assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
}

#[test]
#[cfg(not(target_os = "redox"))]
fn test_sigaction() {
Expand Down

0 comments on commit 97efade

Please sign in to comment.