1use arch_rs::{arch_copy_from_user, arch_copy_to_user};
8use core::mem::MaybeUninit;
9use zerocopy::{FromBytes, Immutable, IntoBytes};
10use zx_status::Status;
11
12#[repr(transparent)]
14#[derive(Debug, Copy, Clone, Default)]
15pub struct UserInPtr<T> {
16 ptr: *const T,
17}
18
19impl<T> UserInPtr<T> {
20 pub const fn new(ptr: *const T) -> Self {
22 Self { ptr }
23 }
24
25 pub fn is_null(&self) -> bool {
27 self.ptr.is_null()
28 }
29
30 pub fn as_ptr(&self) -> *const T {
32 self.ptr
33 }
34
35 pub fn byte_offset(&self, count: isize) -> Self {
37 if self.ptr.is_null() {
38 return Self::new(core::ptr::null());
39 }
40 Self::new(self.ptr.wrapping_byte_offset(count))
41 }
42
43 pub fn element_offset(&self, index: usize) -> Self {
45 if self.ptr.is_null() {
46 return Self::new(core::ptr::null());
47 }
48 Self::new(self.ptr.wrapping_add(index))
49 }
50
51 pub fn reinterpret<U>(&self) -> UserInPtr<U> {
53 UserInPtr::new(self.ptr.cast::<U>())
54 }
55
56 pub fn copy_from_user<'a>(&self, dst: &'a mut MaybeUninit<T>) -> Result<&'a mut T, Status>
58 where
59 T: FromBytes + IntoBytes,
60 {
61 unsafe {
66 arch_copy_from_user(
67 dst.as_mut_ptr() as *mut core::ffi::c_void,
68 self.ptr as *const core::ffi::c_void,
69 core::mem::size_of::<T>(),
70 )?;
71 Ok(dst.assume_init_mut())
72 }
73 }
74
75 pub fn read(&self) -> Result<T, Status>
77 where
78 T: FromBytes + IntoBytes + Immutable,
79 {
80 let mut val = MaybeUninit::uninit();
81 self.copy_from_user(&mut val)?;
82 Ok(unsafe { val.assume_init() })
85 }
86
87 pub fn copy_slice_from_user<'a>(
89 &self,
90 dst: &'a mut [MaybeUninit<T>],
91 ) -> Result<&'a mut [T], Status>
92 where
93 T: FromBytes + IntoBytes,
94 {
95 let len_bytes = core::mem::size_of_val(dst);
96 unsafe {
101 arch_copy_from_user(
102 dst.as_mut_ptr() as *mut core::ffi::c_void,
103 self.ptr as *const core::ffi::c_void,
104 len_bytes,
105 )?;
106 Ok(core::slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut T, dst.len()))
107 }
108 }
109}
110
111#[repr(transparent)]
113#[derive(Debug, Copy, Clone, Default)]
114pub struct UserOutPtr<T> {
115 ptr: *mut T,
116}
117
118impl<T> UserOutPtr<T> {
119 pub const fn new(ptr: *mut T) -> Self {
121 Self { ptr }
122 }
123
124 pub fn is_null(&self) -> bool {
126 self.ptr.is_null()
127 }
128
129 pub fn as_ptr(&self) -> *mut T {
131 self.ptr
132 }
133
134 pub fn byte_offset(&self, count: isize) -> Self {
136 if self.ptr.is_null() {
137 return Self::new(core::ptr::null_mut());
138 }
139 Self::new(self.ptr.wrapping_byte_offset(count))
140 }
141
142 pub fn element_offset(&self, index: usize) -> Self {
144 if self.ptr.is_null() {
145 return Self::new(core::ptr::null_mut());
146 }
147 Self::new(self.ptr.wrapping_add(index))
148 }
149
150 pub fn reinterpret<U>(&self) -> UserOutPtr<U> {
152 UserOutPtr::new(self.ptr.cast::<U>())
153 }
154
155 pub fn copy_to_user(&self, src: &T) -> Result<(), Status>
157 where
158 T: IntoBytes + Immutable,
159 {
160 let src_bytes = src.as_bytes();
161 unsafe {
163 arch_copy_to_user(
164 self.ptr as *mut core::ffi::c_void,
165 src_bytes.as_ptr() as *const core::ffi::c_void,
166 src_bytes.len(),
167 )
168 }
169 }
170
171 pub fn write(&self, val: T) -> Result<(), Status>
173 where
174 T: IntoBytes + Immutable,
175 {
176 self.copy_to_user(&val)
177 }
178
179 pub fn copy_slice_to_user(&self, src: &[T]) -> Result<(), Status>
181 where
182 T: IntoBytes + Immutable,
183 {
184 let src_bytes = src.as_bytes();
185 unsafe {
188 arch_copy_to_user(
189 self.ptr as *mut core::ffi::c_void,
190 src_bytes.as_ptr() as *const core::ffi::c_void,
191 src_bytes.len(),
192 )
193 }
194 }
195}
196
197#[repr(transparent)]
199#[derive(Debug, Copy, Clone, Default)]
200pub struct UserInOutPtr<T> {
201 ptr: *mut T,
202}
203
204impl<T> UserInOutPtr<T> {
205 pub const fn new(ptr: *mut T) -> Self {
207 Self { ptr }
208 }
209
210 pub fn is_null(&self) -> bool {
212 self.ptr.is_null()
213 }
214
215 pub fn as_ptr(&self) -> *mut T {
217 self.ptr
218 }
219
220 pub fn byte_offset(&self, count: isize) -> Self {
222 if self.ptr.is_null() {
223 return Self::new(core::ptr::null_mut());
224 }
225 Self::new(self.ptr.wrapping_byte_offset(count))
226 }
227
228 pub fn element_offset(&self, index: usize) -> Self {
230 if self.ptr.is_null() {
231 return Self::new(core::ptr::null_mut());
232 }
233 Self::new(self.ptr.wrapping_add(index))
234 }
235
236 pub fn reinterpret<U>(&self) -> UserInOutPtr<U> {
238 UserInOutPtr::new(self.ptr.cast::<U>())
239 }
240
241 pub const fn as_in_ptr(&self) -> UserInPtr<T> {
243 UserInPtr::new(self.ptr)
244 }
245
246 pub const fn as_out_ptr(&self) -> UserOutPtr<T> {
248 UserOutPtr::new(self.ptr)
249 }
250
251 pub fn copy_from_user<'a>(&self, dst: &'a mut MaybeUninit<T>) -> Result<&'a mut T, Status>
253 where
254 T: FromBytes + IntoBytes,
255 {
256 self.as_in_ptr().copy_from_user(dst)
257 }
258
259 pub fn read(&self) -> Result<T, Status>
261 where
262 T: FromBytes + IntoBytes + Immutable,
263 {
264 self.as_in_ptr().read()
265 }
266
267 pub fn copy_slice_from_user<'a>(
269 &self,
270 dst: &'a mut [MaybeUninit<T>],
271 ) -> Result<&'a mut [T], Status>
272 where
273 T: FromBytes + IntoBytes,
274 {
275 self.as_in_ptr().copy_slice_from_user(dst)
276 }
277
278 pub fn copy_to_user(&self, src: &T) -> Result<(), Status>
280 where
281 T: IntoBytes + Immutable,
282 {
283 self.as_out_ptr().copy_to_user(src)
284 }
285
286 pub fn write(&self, val: T) -> Result<(), Status>
288 where
289 T: IntoBytes + Immutable,
290 {
291 self.as_out_ptr().write(val)
292 }
293
294 pub fn copy_slice_to_user(&self, src: &[T]) -> Result<(), Status>
296 where
297 T: IntoBytes + Immutable,
298 {
299 self.as_out_ptr().copy_slice_to_user(src)
300 }
301}