#![allow(unsafe_code)]
use crate::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use core::fmt;
use core::marker::PhantomData;
use core::ops::Deref;
pub struct Ref<'a, T> {
t: T,
_phantom: PhantomData<&'a T>,
}
impl<'a, T> Ref<'a, T> {
#[inline]
fn new(t: T) -> Self {
Self {
t,
_phantom: PhantomData,
}
}
#[inline]
fn consume(self) -> T {
self.t
}
}
impl<'a, T> Deref for Ref<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.t
}
}
impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.t.fmt(fmt)
}
}
pub trait Context {
type Data;
type Target: AsFd;
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
}
pub struct Borrowing<'a> {
_phantom: PhantomData<BorrowedFd<'a>>,
}
impl<'a> Context for Borrowing<'a> {
type Data = BorrowedFd<'a>;
type Target = BorrowedFd<'a>;
#[inline]
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
Ref::new(data)
}
#[inline]
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
target.as_raw_fd() as u64
}
#[inline]
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
}
#[inline]
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
target.consume()
}
}
#[cfg(not(feature = "rustc-dep-of-std"))]
pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
_phantom: PhantomData<&'context T>,
}
#[cfg(not(feature = "rustc-dep-of-std"))]
impl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> {
#[allow(clippy::new_without_default)] #[inline]
pub fn new() -> Self {
Self {
_phantom: PhantomData,
}
}
}
#[cfg(not(feature = "rustc-dep-of-std"))]
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> {
type Data = T;
type Target = BorrowedFd<'context>;
#[inline]
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
let fd: OwnedFd = data.into();
let raw_fd = fd.into_raw_fd();
unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
}
#[inline]
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
target.as_fd().as_raw_fd() as u64
}
#[inline]
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
}
#[inline]
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
let raw_fd = target.consume().as_raw_fd();
unsafe { T::from(OwnedFd::from_raw_fd(raw_fd).into()) }
}
}