Skip to main content

zx/
macros.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Implements the common traits for a Handle newtype struct
6macro_rules! impl_handle_based {
7    ($type_name:path) => {
8        impl $crate::AsHandleRef for $type_name {
9            fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
10                self.0.as_handle_ref()
11            }
12        }
13
14        impl From<$crate::NullableHandle> for $type_name {
15            fn from(handle: $crate::NullableHandle) -> Self {
16                $type_name(handle)
17            }
18        }
19
20        impl From<$crate::Handle> for $type_name {
21            fn from(handle: $crate::Handle) -> Self {
22                $type_name(handle.into())
23            }
24        }
25
26        impl From<$type_name> for $crate::NullableHandle {
27            fn from(x: $type_name) -> $crate::NullableHandle {
28                x.0
29            }
30        }
31
32        impl TryFrom<$type_name> for $crate::Handle {
33            type Error = $crate::Status;
34
35            fn try_from(x: $type_name) -> Result<$crate::Handle, Self::Error> {
36                Ok($crate::Handle::try_from(x.0)?)
37            }
38        }
39
40        impl $type_name {
41            delegated_concrete_handle_based_impls!(Self);
42        }
43    };
44    ($type_name:ident, [$($impl_generics:tt)*], [$($ty_generics:tt)*]) => {
45        impl<$($impl_generics)*> crate::AsHandleRef for $type_name<$($ty_generics)*> {
46            fn as_handle_ref(&self) -> crate::HandleRef<'_> {
47                self.0.as_handle_ref()
48            }
49        }
50
51        impl<$($impl_generics)*> AsRef<crate::NullableHandle> for $type_name<$($ty_generics)*> {
52            fn as_ref(&self) -> &crate::NullableHandle {
53                &self.0
54            }
55        }
56
57        impl<$($impl_generics)*> From<crate::NullableHandle> for $type_name<$($ty_generics)*> {
58            fn from(handle: crate::NullableHandle) -> Self {
59                $type_name(handle, ::std::marker::PhantomData)
60            }
61        }
62
63        impl<$($impl_generics)*> From<$crate::Handle> for $type_name<$($ty_generics)*> {
64            fn from(handle: $crate::Handle) -> Self {
65                $type_name(handle.into(), ::std::marker::PhantomData)
66            }
67        }
68
69
70        impl<$($impl_generics)*> From<$type_name<$($ty_generics)*>> for crate::NullableHandle {
71            fn from(x: $type_name<$($ty_generics)*>) -> crate::NullableHandle {
72                x.0
73            }
74        }
75
76        impl<$($impl_generics)*> TryFrom<$type_name<$($ty_generics)*>> for $crate::Handle {
77            type Error = $crate::Status;
78
79            fn try_from(x: $type_name<$($ty_generics)*>) -> Result<$crate::Handle, Self::Error> {
80                Ok($crate::Handle::try_from(x.0)?)
81            }
82        }
83
84        impl<$($impl_generics)*> $type_name<$($ty_generics)*> {
85            delegated_concrete_handle_based_impls!(|h| Self(h, ::std::marker::PhantomData));
86        }
87    };
88}
89
90macro_rules! delegated_concrete_handle_based_impls {
91    ($ctor:expr) => {
92        /// Return the handle's integer value.
93        pub fn raw_handle(&self) -> $crate::sys::zx_handle_t {
94            self.0.raw_handle()
95        }
96
97        // TODO(https://fxbug.dev/465766514) remove with NullableHandle migration
98        pub fn invalid() -> Self {
99            $ctor($crate::NullableHandle::invalid())
100        }
101
102        // TODO(https://fxbug.dev/465766514) remove with NullableHandle migration
103        pub fn is_invalid(&self) -> bool {
104            self.0.is_invalid()
105        }
106
107        /// Return the raw handle's integer value without closing it when `self` is dropped.
108        pub fn into_raw(self) -> $crate::sys::zx_handle_t {
109            self.0.into_raw()
110        }
111
112        /// Returns an [Unowned] referring to this handle.
113        pub fn unowned(&self) -> $crate::Unowned<'_, Self> {
114            $crate::Unowned::cast(self.as_handle_ref())
115        }
116
117        /// Returns a [HandleRef] referring to this handle.
118        pub fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
119            self.0.as_handle_ref()
120        }
121
122        // TODO(https://fxbug.dev/384752843) only generate on types that can be duped
123        /// Wraps the
124        /// [`zx_handle_duplicate`](https://fuchsia.dev/fuchsia-src/reference/syscalls/handle_duplicate)
125        /// syscall.
126        pub fn duplicate_handle(&self, rights: $crate::Rights) -> Result<Self, $crate::Status> {
127            self.0.duplicate_handle(rights).map($ctor)
128        }
129
130        /// Wraps the
131        /// [`zx_handle_replace`](https://fuchsia.dev/fuchsia-src/reference/syscalls/handle_replace)
132        /// syscall.
133        pub fn replace_handle(self, rights: $crate::Rights) -> Result<Self, $crate::Status> {
134            self.0.replace_handle(rights).map($ctor)
135        }
136
137        /// Converts the value into its inner handle.
138        pub fn into_handle(self) -> $crate::NullableHandle {
139            self.into()
140        }
141
142        /// Wraps the
143        /// [`zx_object_signal`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_signal)
144        /// syscall.
145        pub fn signal(
146            &self,
147            clear_mask: $crate::Signals,
148            set_mask: $crate::Signals,
149        ) -> Result<(), $crate::Status> {
150            self.0.signal(clear_mask, set_mask)
151        }
152
153        /// Wraps the
154        /// [`zx_object_wait_one`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_wait_one)
155        /// syscall.
156        pub fn wait_one(
157            &self,
158            signals: $crate::Signals,
159            deadline: $crate::MonotonicInstant,
160        ) -> $crate::WaitResult {
161            self.0.wait_one(signals, deadline)
162        }
163
164        /// Wraps the
165        /// [`zx_object_wait_async`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_wait_async)
166        /// syscall.
167        pub fn wait_async(
168            &self,
169            port: &$crate::Port,
170            key: u64,
171            signals: $crate::Signals,
172            options: $crate::WaitAsyncOpts,
173        ) -> Result<(), $crate::Status> {
174            self.0.wait_async(port, key, signals, options)
175        }
176
177        /// Return a `WaitItem` for this handle and the provided `signals` to use with
178        /// `object_wait_many`.
179        pub fn wait_item(&self, signals: $crate::Signals) -> $crate::WaitItem<'_> {
180            self.0.wait_item(signals)
181        }
182
183        /// Wraps a call to the
184        /// [`zx_object_get_property`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_property)
185        /// syscall for the `ZX_PROP_NAME` property.
186        pub fn get_name(&self) -> Result<$crate::Name, $crate::Status> {
187            self.0.get_name()
188        }
189
190        /// Wraps a call to the
191        /// [`zx_object_set_property`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_set_property)
192        /// syscall for the `ZX_PROP_NAME` property.
193        pub fn set_name(&self, name: &$crate::Name) -> Result<(), $crate::Status> {
194            self.0.set_name(name)
195        }
196
197        /// Wraps the
198        /// [`zx_object_get_info`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info)
199        /// syscall for the `ZX_INFO_HANDLE_BASIC` topic.
200        pub fn basic_info(&self) -> Result<$crate::HandleBasicInfo, $crate::Status> {
201            self.0.basic_info()
202        }
203
204        /// Wraps the
205        /// [`zx_object_get_info`](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info)
206        /// syscall for the `ZX_INFO_HANDLE_COUNT` topic.
207        pub fn count_info(&self) -> Result<$crate::HandleCountInfo, $crate::Status> {
208            self.0.count_info()
209        }
210
211        /// Returns the [Koid] for the object referred to by this handle.
212        pub fn koid(&self) -> Result<$crate::Koid, $crate::Status> {
213            self.0.koid()
214        }
215    };
216}
217
218/// Convenience macro for creating get/set property functions on an object.
219///
220/// This is for use when the underlying property type is a simple raw type.
221/// It creates an empty 'tag' struct to implement the relevant PropertyQuery*
222/// traits against. One, or both, of a getter and setter may be defined
223/// depending upon what the property supports. Example usage is
224/// unsafe_handle_propertyes!(ObjectType[get_foo_prop,set_foo_prop:FooPropTag,FOO,u32;]);
225/// unsafe_handle_properties!(object: Foo,
226///     props: [
227///         {query_ty: FOO_BAR, tag: FooBarTag, prop_ty: usize, get:get_bar},
228///         {query_ty: FOO_BAX, tag: FooBazTag, prop_ty: u32, set:set_baz},
229///     ]
230/// );
231/// And will create
232/// Foo::get_bar(&self) -> Result<usize, Status>
233/// Foo::set_baz(&self, val: &u32) -> Result<(), Status>
234/// Using Property::FOO as the underlying property.
235///
236///  # Safety
237///
238/// This macro will implement unsafe traits on your behalf and any combination
239/// of query_ty and prop_ty must respect the Safety requirements detailed on the
240/// PropertyQuery trait.
241macro_rules! unsafe_handle_properties {
242    (
243        object: $object_ty:ty,
244        props: [$( {
245            query_ty: $query_ty:ident,
246            tag: $query_tag:ident,
247            prop_ty: $prop_ty:ty
248            $(,get: $get:ident)*
249            $(,set: $set:ident)*
250            $(,)*
251        }),*$(,)*]
252    ) => {
253        $(
254            struct $query_tag {}
255            unsafe impl $crate::PropertyQuery for $query_tag {
256                const PROPERTY: $crate::Property = $crate::Property::$query_ty;
257                type PropTy = $prop_ty;
258            }
259
260            $(
261                impl $object_ty {
262                    pub fn $get(&self) -> Result<$prop_ty, $crate::Status> {
263                        self.0.get_property::<$query_tag>()
264                    }
265                }
266            )*
267
268            $(
269                impl $object_ty {
270                    pub fn $set(&self, val: &$prop_ty) -> Result<(), $crate::Status> {
271                        self.0.set_property::<$query_tag>(val)
272                    }
273                }
274            )*
275        )*
276    }
277}
278
279// Creates associated constants of TypeName of the form
280// `pub const NAME: TypeName = TypeName(path::to::value);`
281// and provides a private `assoc_const_name` method and a `Debug` implementation
282// for the type based on `$name`.
283// If multiple names match, the first will be used in `name` and `Debug`.
284#[macro_export]
285macro_rules! assoc_values {
286    ($typename:ident, [$($(#[$attr:meta])* $name:ident = $value:path;)*]) => {
287        #[allow(non_upper_case_globals)]
288        impl $typename {
289            $(
290                $(#[$attr])*
291                pub const $name: $typename = $typename($value);
292            )*
293
294            fn assoc_const_name(&self) -> Option<&'static str> {
295                match self.0 {
296                    $(
297                        $(#[$attr])*
298                        $value => Some(stringify!($name)),
299                    )*
300                    _ => None,
301                }
302            }
303        }
304
305        impl ::std::fmt::Debug for $typename {
306            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
307                f.write_str(concat!(stringify!($typename), "("))?;
308                match self.assoc_const_name() {
309                    Some(name) => f.write_str(&name)?,
310                    None => ::std::fmt::Debug::fmt(&self.0, f)?,
311                }
312                f.write_str(")")
313            }
314        }
315    }
316}
317
318/// Declare a struct that needs to be statically aligned with another, equivalent struct. The syntax
319/// is the following:
320/// rust```
321/// static_assert_align! (
322///     #[derive(Trait1, Trait2)]
323///     <other_aligned_struct> pub struct MyStruct {
324///         field_1 <equivalent_field1_on_other_struct>: bool,
325///         field_2 <equivalent_field2_on_other_struct>: u32,
326///         special_field_3: [u8; 10],  // This field will be ignored when comparing alignment.
327///     }
328/// );
329/// ```
330macro_rules! static_assert_align {
331    (
332        $(#[$attrs:meta])* <$equivalent:ty> $vis:vis struct $struct_name:ident {
333            $($field_vis:vis $field_ident:ident $(<$field_eq:ident>)?: $field_type:ty,)*
334        }
335    ) => {
336        $(#[$attrs])* $vis struct $struct_name {
337            $($field_vis $field_ident: $field_type,)*
338        }
339
340        static_assertions::assert_eq_size!($struct_name, $equivalent);
341        $(_static_assert_one_field!($struct_name, $field_ident, $equivalent $(, $field_eq)?);)*
342    }
343}
344
345/// Internal macro used by [static_assert_align].
346macro_rules! _static_assert_one_field {
347    ($struct_1:ty, $field_1:ident, $struct_2:ty) => {};
348    ($struct_1:ty, $field_1:ident, $struct_2:ty, $field_2:ident) => {
349        static_assertions::const_assert_eq!(
350            std::mem::offset_of!($struct_1, $field_1),
351            std::mem::offset_of!($struct_2, $field_2)
352        );
353    };
354}