summaryrefslogtreecommitdiffstats
path: root/vendor/io-lifetimes/src/views.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/io-lifetimes/src/views.rs')
-rw-r--r--vendor/io-lifetimes/src/views.rs204
1 files changed, 204 insertions, 0 deletions
diff --git a/vendor/io-lifetimes/src/views.rs b/vendor/io-lifetimes/src/views.rs
new file mode 100644
index 000000000..aec3750a0
--- /dev/null
+++ b/vendor/io-lifetimes/src/views.rs
@@ -0,0 +1,204 @@
+//! Typed views using temporary objects.
+//!
+//! This module defines the return types for [`AsFilelike::as_filelike_view`]
+//! and [`AsSocketlike::as_socketlike_view`].
+//!
+//! [`AsSocketlike::as_socketlike_view`]: crate::AsSocketlike::as_socketlike_view
+
+use crate::raw::{
+ AsRawFilelike, AsRawSocketlike, FromRawFilelike, FromRawSocketlike, IntoRawFilelike,
+ IntoRawSocketlike, RawFilelike, RawSocketlike,
+};
+use crate::{
+ AsFilelike, AsSocketlike, FromFilelike, FromSocketlike, IntoFilelike, IntoSocketlike,
+ OwnedFilelike, OwnedSocketlike,
+};
+use std::fmt;
+use std::marker::PhantomData;
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+
+/// Declare that a type is safe to use in a [`FilelikeView`].
+///
+/// # Safety
+///
+/// Types implementing this trait declare that if they are constructed with
+/// [`FromFilelike`] and consumed with [`IntoFilelike`], their `IntoFilelike`
+/// will return the same `OwnedFd` value that was passed to their
+/// `FromFilelike`.
+pub unsafe trait FilelikeViewType: FromFilelike + IntoFilelike {}
+
+/// Declare that a type is safe to use in a [`SocketlikeView`].
+///
+/// # Safety
+///
+/// Types implementing this trait declare that if they are constructed with
+/// [`FromSocketlike`] and consumed with [`IntoSocketlike`], their
+/// `IntoSocketlike` will return the same `OwnedFd` value that was passed to
+/// their `FromSocketlike`.
+pub unsafe trait SocketlikeViewType: FromSocketlike + IntoSocketlike {}
+
+/// A non-owning view of a resource which dereferences to a `&Target` or
+/// `&mut Target`. These are returned by [`AsFilelike::as_filelike_view`].
+pub struct FilelikeView<'filelike, Target: FilelikeViewType> {
+ /// The value to dereference to. This is a `ManuallyDrop` so that we can
+ /// consume it in our `Drop` impl.
+ target: ManuallyDrop<Target>,
+
+ /// `FilelikeViewType` implementors guarantee that their `Into<OwnedFd>`
+ /// returns the same fd as their `From<OwnedFd>` gave them. This field
+ /// allows us to verify this.
+ #[cfg(debug_assertions)]
+ orig: RawFilelike,
+
+ /// This field exists because we don't otherwise explicitly use
+ /// `'filelike`.
+ _phantom: PhantomData<&'filelike OwnedFilelike>,
+}
+
+/// A non-owning view of a resource which dereferences to a `&Target` or
+/// `&mut Target`. These are returned by [`AsSocketlike::as_socketlike_view`].
+pub struct SocketlikeView<'socketlike, Target: SocketlikeViewType> {
+ /// The value to dereference to. This is a `ManuallyDrop` so that we can
+ /// consume it in our `Drop` impl.
+ target: ManuallyDrop<Target>,
+
+ /// `SocketlikeViewType` implementors guarantee that their `Into<OwnedFd>`
+ /// returns the same fd as their `From<OwnedFd>` gave them. This field
+ /// allows us to verify this.
+ #[cfg(debug_assertions)]
+ orig: RawSocketlike,
+
+ /// This field exists because we don't otherwise explicitly use
+ /// `'socketlike`.
+ _phantom: PhantomData<&'socketlike OwnedSocketlike>,
+}
+
+impl<Target: FilelikeViewType> FilelikeView<'_, Target> {
+ /// Construct a temporary `Target` and wrap it in a `FilelikeView` object.
+ #[inline]
+ pub(crate) fn new<T: AsFilelike>(filelike: &T) -> Self {
+ // Safety: The returned `FilelikeView` is scoped to the lifetime of
+ // `filelike`, which we've borrowed here, so the view won't outlive
+ // the object it's borrowed from.
+ unsafe { Self::view_raw(filelike.as_filelike().as_raw_filelike()) }
+ }
+
+ /// Construct a temporary `Target` from raw and wrap it in a `FilelikeView`
+ /// object.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be a valid raw filelike referencing a resource that outlives
+ /// the resulting view.
+ #[inline]
+ pub unsafe fn view_raw(raw: RawFilelike) -> Self {
+ let owned = OwnedFilelike::from_raw_filelike(raw);
+ Self {
+ target: ManuallyDrop::new(Target::from_filelike(owned)),
+ #[cfg(debug_assertions)]
+ orig: raw,
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl<Target: SocketlikeViewType> SocketlikeView<'_, Target> {
+ /// Construct a temporary `Target` and wrap it in a `SocketlikeView`
+ /// object.
+ #[inline]
+ pub(crate) fn new<T: AsSocketlike>(socketlike: &T) -> Self {
+ // Safety: The returned `SocketlikeView` is scoped to the lifetime of
+ // `socketlike`, which we've borrowed here, so the view won't outlive
+ // the object it's borrowed from.
+ unsafe { Self::view_raw(socketlike.as_socketlike().as_raw_socketlike()) }
+ }
+
+ /// Construct a temporary `Target` from raw and wrap it in a
+ /// `SocketlikeView` object.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be a valid raw socketlike referencing a resource that
+ /// outlives the resulting view.
+ #[inline]
+ pub unsafe fn view_raw(raw: RawSocketlike) -> Self {
+ let owned = OwnedSocketlike::from_raw_socketlike(raw);
+ Self {
+ target: ManuallyDrop::new(Target::from_socketlike(owned)),
+ #[cfg(debug_assertions)]
+ orig: raw,
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl<Target: FilelikeViewType> Deref for FilelikeView<'_, Target> {
+ type Target = Target;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.target
+ }
+}
+
+impl<Target: SocketlikeViewType> Deref for SocketlikeView<'_, Target> {
+ type Target = Target;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.target
+ }
+}
+
+impl<Target: FilelikeViewType> Drop for FilelikeView<'_, Target> {
+ #[inline]
+ fn drop(&mut self) {
+ // Use `Into*` to consume `self.target` without freeing its resource.
+ //
+ // Safety: Using `ManuallyDrop::take` requires us to ensure that
+ // `self.target` is not used again. We don't use it again here, and
+ // this is the `drop` function, so we know it's not used afterward.
+ let _raw = unsafe { ManuallyDrop::take(&mut self.target) }
+ .into_filelike()
+ .into_raw_filelike();
+
+ #[cfg(debug_assertions)]
+ debug_assert_eq!(self.orig, _raw);
+ }
+}
+
+impl<Target: SocketlikeViewType> Drop for SocketlikeView<'_, Target> {
+ #[inline]
+ fn drop(&mut self) {
+ // Use `Into*` to consume `self.target` without freeing its resource.
+ //
+ // Safety: Using `ManuallyDrop::take` requires us to ensure that
+ // `self.target` is not used again. We don't use it again here, and
+ // this is the `drop` function, so we know it's not used afterward.
+ let _raw = unsafe { ManuallyDrop::take(&mut self.target) }
+ .into_socketlike()
+ .into_raw_socketlike();
+
+ #[cfg(debug_assertions)]
+ debug_assert_eq!(self.orig, _raw);
+ }
+}
+
+impl<Target: FilelikeViewType> fmt::Debug for FilelikeView<'_, Target> {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FilelikeView")
+ .field("target", &*self)
+ .finish()
+ }
+}
+
+impl<Target: SocketlikeViewType> fmt::Debug for SocketlikeView<'_, Target> {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("SocketlikeView")
+ .field("target", &*self)
+ .finish()
+ }
+}