1b8a62b91Sopenharmony_ci//! Context types for polling systems, e.g. kqueue and epoll. 2b8a62b91Sopenharmony_ci 3b8a62b91Sopenharmony_ci#![allow(unsafe_code)] 4b8a62b91Sopenharmony_ci 5b8a62b91Sopenharmony_ciuse crate::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; 6b8a62b91Sopenharmony_ci 7b8a62b91Sopenharmony_ciuse core::fmt; 8b8a62b91Sopenharmony_ciuse core::marker::PhantomData; 9b8a62b91Sopenharmony_ciuse core::ops::Deref; 10b8a62b91Sopenharmony_ci 11b8a62b91Sopenharmony_ci/// A reference to a `T`. 12b8a62b91Sopenharmony_cipub struct Ref<'a, T> { 13b8a62b91Sopenharmony_ci t: T, 14b8a62b91Sopenharmony_ci _phantom: PhantomData<&'a T>, 15b8a62b91Sopenharmony_ci} 16b8a62b91Sopenharmony_ci 17b8a62b91Sopenharmony_ciimpl<'a, T> Ref<'a, T> { 18b8a62b91Sopenharmony_ci #[inline] 19b8a62b91Sopenharmony_ci fn new(t: T) -> Self { 20b8a62b91Sopenharmony_ci Self { 21b8a62b91Sopenharmony_ci t, 22b8a62b91Sopenharmony_ci _phantom: PhantomData, 23b8a62b91Sopenharmony_ci } 24b8a62b91Sopenharmony_ci } 25b8a62b91Sopenharmony_ci 26b8a62b91Sopenharmony_ci #[inline] 27b8a62b91Sopenharmony_ci fn consume(self) -> T { 28b8a62b91Sopenharmony_ci self.t 29b8a62b91Sopenharmony_ci } 30b8a62b91Sopenharmony_ci} 31b8a62b91Sopenharmony_ci 32b8a62b91Sopenharmony_ciimpl<'a, T> Deref for Ref<'a, T> { 33b8a62b91Sopenharmony_ci type Target = T; 34b8a62b91Sopenharmony_ci 35b8a62b91Sopenharmony_ci #[inline] 36b8a62b91Sopenharmony_ci fn deref(&self) -> &T { 37b8a62b91Sopenharmony_ci &self.t 38b8a62b91Sopenharmony_ci } 39b8a62b91Sopenharmony_ci} 40b8a62b91Sopenharmony_ci 41b8a62b91Sopenharmony_ciimpl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> { 42b8a62b91Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 43b8a62b91Sopenharmony_ci self.t.fmt(fmt) 44b8a62b91Sopenharmony_ci } 45b8a62b91Sopenharmony_ci} 46b8a62b91Sopenharmony_ci 47b8a62b91Sopenharmony_ci/// A trait for data stored within an [`Epoll`] instance. 48b8a62b91Sopenharmony_ci/// 49b8a62b91Sopenharmony_ci/// [`Epoll`]: crate::io::epoll::Epoll 50b8a62b91Sopenharmony_cipub trait Context { 51b8a62b91Sopenharmony_ci /// The type of an element owned by this context. 52b8a62b91Sopenharmony_ci type Data; 53b8a62b91Sopenharmony_ci 54b8a62b91Sopenharmony_ci /// The type of a value used to refer to an element owned by this context. 55b8a62b91Sopenharmony_ci type Target: AsFd; 56b8a62b91Sopenharmony_ci 57b8a62b91Sopenharmony_ci /// Assume ownership of `data`, and returning a `Target`. 58b8a62b91Sopenharmony_ci fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>; 59b8a62b91Sopenharmony_ci 60b8a62b91Sopenharmony_ci /// Encode `target` as a `u64`. The only requirement on this value is that 61b8a62b91Sopenharmony_ci /// it be decodable by `decode`. 62b8a62b91Sopenharmony_ci fn encode(&self, target: Ref<'_, Self::Target>) -> u64; 63b8a62b91Sopenharmony_ci 64b8a62b91Sopenharmony_ci /// Decode `raw`, which is a value encoded by `encode`, into a `Target`. 65b8a62b91Sopenharmony_ci /// 66b8a62b91Sopenharmony_ci /// # Safety 67b8a62b91Sopenharmony_ci /// 68b8a62b91Sopenharmony_ci /// `raw` must be a `u64` value returned from `encode`, from the same 69b8a62b91Sopenharmony_ci /// context, and within the context's lifetime. 70b8a62b91Sopenharmony_ci unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>; 71b8a62b91Sopenharmony_ci 72b8a62b91Sopenharmony_ci /// Release ownership of the value referred to by `target` and return it. 73b8a62b91Sopenharmony_ci fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data; 74b8a62b91Sopenharmony_ci} 75b8a62b91Sopenharmony_ci 76b8a62b91Sopenharmony_ci/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`. 77b8a62b91Sopenharmony_cipub struct Borrowing<'a> { 78b8a62b91Sopenharmony_ci _phantom: PhantomData<BorrowedFd<'a>>, 79b8a62b91Sopenharmony_ci} 80b8a62b91Sopenharmony_ci 81b8a62b91Sopenharmony_ciimpl<'a> Context for Borrowing<'a> { 82b8a62b91Sopenharmony_ci type Data = BorrowedFd<'a>; 83b8a62b91Sopenharmony_ci type Target = BorrowedFd<'a>; 84b8a62b91Sopenharmony_ci 85b8a62b91Sopenharmony_ci #[inline] 86b8a62b91Sopenharmony_ci fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> { 87b8a62b91Sopenharmony_ci Ref::new(data) 88b8a62b91Sopenharmony_ci } 89b8a62b91Sopenharmony_ci 90b8a62b91Sopenharmony_ci #[inline] 91b8a62b91Sopenharmony_ci fn encode(&self, target: Ref<'_, Self::Target>) -> u64 { 92b8a62b91Sopenharmony_ci target.as_raw_fd() as u64 93b8a62b91Sopenharmony_ci } 94b8a62b91Sopenharmony_ci 95b8a62b91Sopenharmony_ci #[inline] 96b8a62b91Sopenharmony_ci unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> { 97b8a62b91Sopenharmony_ci Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd)) 98b8a62b91Sopenharmony_ci } 99b8a62b91Sopenharmony_ci 100b8a62b91Sopenharmony_ci #[inline] 101b8a62b91Sopenharmony_ci fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data { 102b8a62b91Sopenharmony_ci target.consume() 103b8a62b91Sopenharmony_ci } 104b8a62b91Sopenharmony_ci} 105b8a62b91Sopenharmony_ci 106b8a62b91Sopenharmony_ci/// A type implementing [`Context`] where the `Data` type is `T`, a type 107b8a62b91Sopenharmony_ci/// implementing `From<OwnedFd>` and `From<T> for OwnedFd`. 108b8a62b91Sopenharmony_ci/// 109b8a62b91Sopenharmony_ci/// This may be used with [`OwnedFd`], or higher-level types like 110b8a62b91Sopenharmony_ci/// [`std::fs::File`] or [`std::net::TcpStream`]. 111b8a62b91Sopenharmony_ci#[cfg(not(feature = "rustc-dep-of-std"))] 112b8a62b91Sopenharmony_cipub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> { 113b8a62b91Sopenharmony_ci _phantom: PhantomData<&'context T>, 114b8a62b91Sopenharmony_ci} 115b8a62b91Sopenharmony_ci 116b8a62b91Sopenharmony_ci#[cfg(not(feature = "rustc-dep-of-std"))] 117b8a62b91Sopenharmony_ciimpl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> { 118b8a62b91Sopenharmony_ci /// Creates a new empty `Owning`. 119b8a62b91Sopenharmony_ci #[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible. 120b8a62b91Sopenharmony_ci #[inline] 121b8a62b91Sopenharmony_ci pub fn new() -> Self { 122b8a62b91Sopenharmony_ci Self { 123b8a62b91Sopenharmony_ci _phantom: PhantomData, 124b8a62b91Sopenharmony_ci } 125b8a62b91Sopenharmony_ci } 126b8a62b91Sopenharmony_ci} 127b8a62b91Sopenharmony_ci 128b8a62b91Sopenharmony_ci#[cfg(not(feature = "rustc-dep-of-std"))] 129b8a62b91Sopenharmony_ciimpl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> { 130b8a62b91Sopenharmony_ci type Data = T; 131b8a62b91Sopenharmony_ci type Target = BorrowedFd<'context>; 132b8a62b91Sopenharmony_ci 133b8a62b91Sopenharmony_ci #[inline] 134b8a62b91Sopenharmony_ci fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> { 135b8a62b91Sopenharmony_ci let fd: OwnedFd = data.into(); 136b8a62b91Sopenharmony_ci let raw_fd = fd.into_raw_fd(); 137b8a62b91Sopenharmony_ci // Safety: `epoll` will assign ownership of the file descriptor to the 138b8a62b91Sopenharmony_ci // kernel epoll object. We use `Into<OwnedFd>`+`IntoRawFd` to consume 139b8a62b91Sopenharmony_ci // the `Data` and extract the raw file descriptor and then "borrow" it 140b8a62b91Sopenharmony_ci // with `borrow_raw` knowing that the borrow won't outlive the 141b8a62b91Sopenharmony_ci // kernel epoll object. 142b8a62b91Sopenharmony_ci unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) } 143b8a62b91Sopenharmony_ci } 144b8a62b91Sopenharmony_ci 145b8a62b91Sopenharmony_ci #[inline] 146b8a62b91Sopenharmony_ci fn encode(&self, target: Ref<'_, Self::Target>) -> u64 { 147b8a62b91Sopenharmony_ci target.as_fd().as_raw_fd() as u64 148b8a62b91Sopenharmony_ci } 149b8a62b91Sopenharmony_ci 150b8a62b91Sopenharmony_ci #[inline] 151b8a62b91Sopenharmony_ci unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> { 152b8a62b91Sopenharmony_ci Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd)) 153b8a62b91Sopenharmony_ci } 154b8a62b91Sopenharmony_ci 155b8a62b91Sopenharmony_ci #[inline] 156b8a62b91Sopenharmony_ci fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data { 157b8a62b91Sopenharmony_ci // The file descriptor was held by the kernel epoll object and is now 158b8a62b91Sopenharmony_ci // being released, so we can create a new `OwnedFd` that assumes 159b8a62b91Sopenharmony_ci // ownership. 160b8a62b91Sopenharmony_ci let raw_fd = target.consume().as_raw_fd(); 161b8a62b91Sopenharmony_ci unsafe { T::from(OwnedFd::from_raw_fd(raw_fd).into()) } 162b8a62b91Sopenharmony_ci } 163b8a62b91Sopenharmony_ci} 164