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