]> git.proxmox.com Git - rustc.git/blob - vendor/io-lifetimes/src/views.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / vendor / io-lifetimes / src / views.rs
1 //! Typed views using temporary objects.
2 //!
3 //! This module defines the return types for [`AsFilelike::as_filelike_view`]
4 //! and [`AsSocketlike::as_socketlike_view`].
5 //!
6 //! [`AsSocketlike::as_socketlike_view`]: crate::AsSocketlike::as_socketlike_view
7
8 use crate::raw::{
9 AsRawFilelike, AsRawSocketlike, FromRawFilelike, FromRawSocketlike, IntoRawFilelike,
10 IntoRawSocketlike, RawFilelike, RawSocketlike,
11 };
12 use crate::{
13 AsFilelike, AsSocketlike, FromFilelike, FromSocketlike, IntoFilelike, IntoSocketlike,
14 OwnedFilelike, OwnedSocketlike,
15 };
16 use std::fmt;
17 use std::marker::PhantomData;
18 use std::mem::ManuallyDrop;
19 use std::ops::Deref;
20
21 /// Declare that a type is safe to use in a [`FilelikeView`].
22 ///
23 /// # Safety
24 ///
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
28 /// `FromFilelike`.
29 pub unsafe trait FilelikeViewType: FromFilelike + IntoFilelike {}
30
31 /// Declare that a type is safe to use in a [`SocketlikeView`].
32 ///
33 /// # Safety
34 ///
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 {}
40
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>,
47
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)]
52 orig: RawFilelike,
53
54 /// This field exists because we don't otherwise explicitly use
55 /// `'filelike`.
56 _phantom: PhantomData<&'filelike OwnedFilelike>,
57 }
58
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>,
65
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)]
70 orig: RawSocketlike,
71
72 /// This field exists because we don't otherwise explicitly use
73 /// `'socketlike`.
74 _phantom: PhantomData<&'socketlike OwnedSocketlike>,
75 }
76
77 impl<Target: FilelikeViewType> FilelikeView<'_, Target> {
78 /// Construct a temporary `Target` and wrap it in a `FilelikeView` object.
79 #[inline]
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()) }
85 }
86
87 /// Construct a temporary `Target` from raw and wrap it in a `FilelikeView`
88 /// object.
89 ///
90 /// # Safety
91 ///
92 /// `raw` must be a valid raw filelike referencing a resource that outlives
93 /// the resulting view.
94 #[inline]
95 pub unsafe fn view_raw(raw: RawFilelike) -> Self {
96 let owned = OwnedFilelike::from_raw_filelike(raw);
97 Self {
98 target: ManuallyDrop::new(Target::from_filelike(owned)),
99 #[cfg(debug_assertions)]
100 orig: raw,
101 _phantom: PhantomData,
102 }
103 }
104 }
105
106 impl<Target: SocketlikeViewType> SocketlikeView<'_, Target> {
107 /// Construct a temporary `Target` and wrap it in a `SocketlikeView`
108 /// object.
109 #[inline]
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()) }
115 }
116
117 /// Construct a temporary `Target` from raw and wrap it in a
118 /// `SocketlikeView` object.
119 ///
120 /// # Safety
121 ///
122 /// `raw` must be a valid raw socketlike referencing a resource that
123 /// outlives the resulting view.
124 #[inline]
125 pub unsafe fn view_raw(raw: RawSocketlike) -> Self {
126 let owned = OwnedSocketlike::from_raw_socketlike(raw);
127 Self {
128 target: ManuallyDrop::new(Target::from_socketlike(owned)),
129 #[cfg(debug_assertions)]
130 orig: raw,
131 _phantom: PhantomData,
132 }
133 }
134 }
135
136 impl<Target: FilelikeViewType> Deref for FilelikeView<'_, Target> {
137 type Target = Target;
138
139 #[inline]
140 fn deref(&self) -> &Self::Target {
141 &self.target
142 }
143 }
144
145 impl<Target: SocketlikeViewType> Deref for SocketlikeView<'_, Target> {
146 type Target = Target;
147
148 #[inline]
149 fn deref(&self) -> &Self::Target {
150 &self.target
151 }
152 }
153
154 impl<Target: FilelikeViewType> Drop for FilelikeView<'_, Target> {
155 #[inline]
156 fn drop(&mut self) {
157 // Use `Into*` to consume `self.target` without freeing its resource.
158 //
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) }
163 .into_filelike()
164 .into_raw_filelike();
165
166 #[cfg(debug_assertions)]
167 debug_assert_eq!(self.orig, _raw);
168 }
169 }
170
171 impl<Target: SocketlikeViewType> Drop for SocketlikeView<'_, Target> {
172 #[inline]
173 fn drop(&mut self) {
174 // Use `Into*` to consume `self.target` without freeing its resource.
175 //
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) }
180 .into_socketlike()
181 .into_raw_socketlike();
182
183 #[cfg(debug_assertions)]
184 debug_assert_eq!(self.orig, _raw);
185 }
186 }
187
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)
193 .finish()
194 }
195 }
196
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)
202 .finish()
203 }
204 }