use std::iter::FusedIterator;
use std::ops::Range;
use std::os::fd::RawFd;
use std::str::Split;
use nix::unistd::close;
use crate::Error;
use crate::fd::Fd;
use crate::thin::ThinStr;
#[must_use]
#[derive(Debug)]
pub struct ListenFds(Range<RawFd>);
#[must_use]
#[derive(Debug)]
pub struct ListenFdNames(ThinStr);
impl ListenFds {
pub(crate) const START: RawFd = 3;
#[inline]
pub(crate) const unsafe fn new(num: u32) -> Self {
Self(Range { start: Self::START, end: Self::START + num as RawFd })
}
}
impl Drop for ListenFds {
fn drop(&mut self) {
for fd in &mut self.0 {
let res = close(fd);
debug_assert!(res.is_ok());
}
}
}
impl Iterator for ListenFds {
type Item = Result<Fd, Error>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|fd| unsafe { Fd::try_from(fd) })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl DoubleEndedIterator for ListenFds {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|fd| unsafe { Fd::try_from(fd) })
}
}
impl ExactSizeIterator for ListenFds {}
impl FusedIterator for ListenFds {}
impl ListenFdNames {
#[inline]
pub(crate) const fn new(names: ThinStr) -> Self { Self(names) }
}
impl<'i> IntoIterator for &'i ListenFdNames {
type IntoIter = Split<'i, char>;
type Item = &'i str;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.0.as_str().split(':') }
}