1 //! Typed views using temporary objects.
3 //! This module defines the return types for [`AsFilelike::as_filelike_view`]
4 //! and [`AsSocketlike::as_socketlike_view`].
6 //! [`AsSocketlike::as_socketlike_view`]: crate::AsSocketlike::as_socketlike_view
9 AsRawFilelike
, AsRawSocketlike
, FromRawFilelike
, FromRawSocketlike
, IntoRawFilelike
,
10 IntoRawSocketlike
, RawFilelike
, RawSocketlike
,
13 AsFilelike
, AsSocketlike
, FromFilelike
, FromSocketlike
, IntoFilelike
, IntoSocketlike
,
14 OwnedFilelike
, OwnedSocketlike
,
17 use std
::marker
::PhantomData
;
18 use std
::mem
::ManuallyDrop
;
21 /// Declare that a type is safe to use in a [`FilelikeView`].
25 /// Types implementing this trait declare that if they are constructed with
26 /// [`FromFilelike`] and consumed with [`IntoFilelike`], their `IntoFilelike`
27 /// will return the same `OwnedFd` value that was passed to their
29 pub unsafe trait FilelikeViewType
: FromFilelike
+ IntoFilelike {}
31 /// Declare that a type is safe to use in a [`SocketlikeView`].
35 /// Types implementing this trait declare that if they are constructed with
36 /// [`FromSocketlike`] and consumed with [`IntoSocketlike`], their
37 /// `IntoSocketlike` will return the same `OwnedFd` value that was passed to
38 /// their `FromSocketlike`.
39 pub unsafe trait SocketlikeViewType
: FromSocketlike
+ IntoSocketlike {}
41 /// A non-owning view of a resource which dereferences to a `&Target` or
42 /// `&mut Target`. These are returned by [`AsFilelike::as_filelike_view`].
43 pub struct FilelikeView
<'filelike
, Target
: FilelikeViewType
> {
44 /// The value to dereference to. This is a `ManuallyDrop` so that we can
45 /// consume it in our `Drop` impl.
46 target
: ManuallyDrop
<Target
>,
48 /// `FilelikeViewType` implementors guarantee that their `Into<OwnedFd>`
49 /// returns the same fd as their `From<OwnedFd>` gave them. This field
50 /// allows us to verify this.
51 #[cfg(debug_assertions)]
54 /// This field exists because we don't otherwise explicitly use
56 _phantom
: PhantomData
<&'filelike OwnedFilelike
>,
59 /// A non-owning view of a resource which dereferences to a `&Target` or
60 /// `&mut Target`. These are returned by [`AsSocketlike::as_socketlike_view`].
61 pub struct SocketlikeView
<'socketlike
, Target
: SocketlikeViewType
> {
62 /// The value to dereference to. This is a `ManuallyDrop` so that we can
63 /// consume it in our `Drop` impl.
64 target
: ManuallyDrop
<Target
>,
66 /// `SocketlikeViewType` implementors guarantee that their `Into<OwnedFd>`
67 /// returns the same fd as their `From<OwnedFd>` gave them. This field
68 /// allows us to verify this.
69 #[cfg(debug_assertions)]
72 /// This field exists because we don't otherwise explicitly use
74 _phantom
: PhantomData
<&'socketlike OwnedSocketlike
>,
77 impl<Target
: FilelikeViewType
> FilelikeView
<'_
, Target
> {
78 /// Construct a temporary `Target` and wrap it in a `FilelikeView` object.
80 pub(crate) fn new
<T
: AsFilelike
>(filelike
: &T
) -> Self {
81 // Safety: The returned `FilelikeView` is scoped to the lifetime of
82 // `filelike`, which we've borrowed here, so the view won't outlive
83 // the object it's borrowed from.
84 unsafe { Self::view_raw(filelike.as_filelike().as_raw_filelike()) }
87 /// Construct a temporary `Target` from raw and wrap it in a `FilelikeView`
92 /// `raw` must be a valid raw filelike referencing a resource that outlives
93 /// the resulting view.
95 pub unsafe fn view_raw(raw
: RawFilelike
) -> Self {
96 let owned
= OwnedFilelike
::from_raw_filelike(raw
);
98 target
: ManuallyDrop
::new(Target
::from_filelike(owned
)),
99 #[cfg(debug_assertions)]
101 _phantom
: PhantomData
,
106 impl<Target
: SocketlikeViewType
> SocketlikeView
<'_
, Target
> {
107 /// Construct a temporary `Target` and wrap it in a `SocketlikeView`
110 pub(crate) fn new
<T
: AsSocketlike
>(socketlike
: &T
) -> Self {
111 // Safety: The returned `SocketlikeView` is scoped to the lifetime of
112 // `socketlike`, which we've borrowed here, so the view won't outlive
113 // the object it's borrowed from.
114 unsafe { Self::view_raw(socketlike.as_socketlike().as_raw_socketlike()) }
117 /// Construct a temporary `Target` from raw and wrap it in a
118 /// `SocketlikeView` object.
122 /// `raw` must be a valid raw socketlike referencing a resource that
123 /// outlives the resulting view.
125 pub unsafe fn view_raw(raw
: RawSocketlike
) -> Self {
126 let owned
= OwnedSocketlike
::from_raw_socketlike(raw
);
128 target
: ManuallyDrop
::new(Target
::from_socketlike(owned
)),
129 #[cfg(debug_assertions)]
131 _phantom
: PhantomData
,
136 impl<Target
: FilelikeViewType
> Deref
for FilelikeView
<'_
, Target
> {
137 type Target
= Target
;
140 fn deref(&self) -> &Self::Target
{
145 impl<Target
: SocketlikeViewType
> Deref
for SocketlikeView
<'_
, Target
> {
146 type Target
= Target
;
149 fn deref(&self) -> &Self::Target
{
154 impl<Target
: FilelikeViewType
> Drop
for FilelikeView
<'_
, Target
> {
157 // Use `Into*` to consume `self.target` without freeing its resource.
159 // Safety: Using `ManuallyDrop::take` requires us to ensure that
160 // `self.target` is not used again. We don't use it again here, and
161 // this is the `drop` function, so we know it's not used afterward.
162 let _raw
= unsafe { ManuallyDrop::take(&mut self.target) }
164 .into_raw_filelike();
166 #[cfg(debug_assertions)]
167 debug_assert_eq
!(self.orig
, _raw
);
171 impl<Target
: SocketlikeViewType
> Drop
for SocketlikeView
<'_
, Target
> {
174 // Use `Into*` to consume `self.target` without freeing its resource.
176 // Safety: Using `ManuallyDrop::take` requires us to ensure that
177 // `self.target` is not used again. We don't use it again here, and
178 // this is the `drop` function, so we know it's not used afterward.
179 let _raw
= unsafe { ManuallyDrop::take(&mut self.target) }
181 .into_raw_socketlike();
183 #[cfg(debug_assertions)]
184 debug_assert_eq
!(self.orig
, _raw
);
188 impl<Target
: FilelikeViewType
> fmt
::Debug
for FilelikeView
<'_
, Target
> {
189 #[allow(clippy::missing_inline_in_public_items)]
190 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
191 f
.debug_struct("FilelikeView")
192 .field("target", &*self)
197 impl<Target
: SocketlikeViewType
> fmt
::Debug
for SocketlikeView
<'_
, Target
> {
198 #[allow(clippy::missing_inline_in_public_items)]
199 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
200 f
.debug_struct("SocketlikeView")
201 .field("target", &*self)