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