use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
#[derive(Debug)]
pub(crate) enum MaybeOwnedFd<'fd, Fd>
where
Fd: AsFd,
{
OwnedFd(Fd),
BorrowedFd(BorrowedFd<'fd>),
}
impl<'fd> From<OwnedFd> for MaybeOwnedFd<'fd, OwnedFd> {
fn from(fd: OwnedFd) -> Self {
Self::OwnedFd(fd)
}
}
impl<'fd, Fd> From<BorrowedFd<'fd>> for MaybeOwnedFd<'fd, Fd>
where
Fd: AsFd,
{
fn from(fd: BorrowedFd<'fd>) -> Self {
Self::BorrowedFd(fd)
}
}
impl<'fd, Fd> MaybeOwnedFd<'fd, Fd>
where
Fd: AsFd,
{
pub(crate) fn try_into_owned(self) -> Result<Fd, Self> {
match self {
Self::OwnedFd(fd) => Ok(fd),
Self::BorrowedFd(_) => Err(self),
}
}
pub(crate) fn into_owned(self) -> Option<Fd> {
self.try_into_owned().ok()
}
pub(crate) fn as_fd<'a>(&'a self) -> BorrowedFd<'a>
where
'a: 'fd,
{
match self {
Self::OwnedFd(fd) => fd.as_fd(),
Self::BorrowedFd(fd) => fd.as_fd(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::{
fs::File,
os::unix::io::{AsFd, AsRawFd, OwnedFd},
};
use anyhow::Error;
use pretty_assertions::{assert_eq, assert_matches};
#[test]
fn as_fd() -> Result<(), Error> {
let f: OwnedFd = File::open(".")?.into();
let fd = f.as_raw_fd();
let owned: MaybeOwnedFd<OwnedFd> = f.into();
assert_matches!(owned, MaybeOwnedFd::OwnedFd(_));
assert_eq!(owned.as_fd().as_raw_fd(), fd);
assert_matches!(owned.into_owned(), Some(_));
let f = File::open(".")?;
let borrowed: MaybeOwnedFd<OwnedFd> = f.as_fd().into();
assert_matches!(borrowed, MaybeOwnedFd::BorrowedFd(_));
assert_matches!(borrowed.into_owned(), None);
Ok(())
}
#[test]
fn into_owned() -> Result<(), Error> {
let f: OwnedFd = File::open(".")?.into();
let owned: MaybeOwnedFd<OwnedFd> = f.into();
assert_matches!(
owned,
MaybeOwnedFd::OwnedFd(_),
"MaybeOwnedFd::from(OwnedFd)"
);
assert_matches!(
owned.into_owned(),
Some(_),
"MaybeOwnedFd::from(OwnedFd).into_owned()"
);
let f = File::open(".")?;
let borrowed: MaybeOwnedFd<OwnedFd> = f.as_fd().into();
assert_matches!(
borrowed,
MaybeOwnedFd::BorrowedFd(_),
"MaybeOwnedFd::from(BorrowedFd)"
);
assert_matches!(
borrowed.into_owned(),
None,
"MaybeOwnedFd::from(BorrowedFd).into_owned()"
);
Ok(())
}
#[test]
fn try_into_owned() -> Result<(), Error> {
let f: OwnedFd = File::open(".")?.into();
let owned: MaybeOwnedFd<OwnedFd> = f.into();
assert_matches!(
owned,
MaybeOwnedFd::OwnedFd(_),
"MaybeOwnedFd::from(OwnedFd)"
);
assert_matches!(
owned.try_into_owned(),
Ok(_),
"MaybeOwnedFd::from(OwnedFd).try_into_owned()"
);
let f = File::open(".")?;
let borrowed: MaybeOwnedFd<OwnedFd> = f.as_fd().into();
assert_matches!(
borrowed,
MaybeOwnedFd::BorrowedFd(_),
"MaybeOwnedFd::from(BorrowedFd)"
);
assert_matches!(
borrowed.try_into_owned(),
Err(_),
"MaybeOwnedFd::from(BorrowedFd).try_into_owned()"
);
Ok(())
}
}