fidl_next_codec/fuchsia/
handle.rs1use core::fmt;
6use core::mem::{MaybeUninit, forget};
7
8use zx::Handle;
9use zx::sys::{ZX_HANDLE_INVALID, zx_handle_t};
10
11use crate::fuchsia::{HandleDecoder, HandleEncoder};
12use crate::{
13 Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption, FromWire,
14 FromWireOption, IntoNatural, Slot, Wire, WireU32, munge,
15};
16
17#[repr(C, align(4))]
19pub union WireHandle {
20 encoded: WireU32,
21 decoded: zx_handle_t,
22}
23
24impl Drop for WireHandle {
25 fn drop(&mut self) {
26 let handle = unsafe { Handle::from_raw(self.as_raw_handle()) };
28 drop(handle);
29 }
30}
31
32unsafe impl Wire for WireHandle {
33 type Decoded<'de> = Self;
34
35 #[inline]
36 fn zero_padding(_: &mut MaybeUninit<Self>) {
37 }
39}
40
41impl WireHandle {
42 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
44 munge!(let Self { encoded } = out);
45 encoded.write(WireU32(u32::MAX));
46 }
47
48 pub fn is_invalid(&self) -> bool {
50 self.as_raw_handle() == ZX_HANDLE_INVALID
51 }
52
53 #[inline]
55 pub fn as_raw_handle(&self) -> zx_handle_t {
56 unsafe { self.decoded }
57 }
58}
59
60impl fmt::Debug for WireHandle {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 self.as_raw_handle().fmt(f)
63 }
64}
65
66unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
67 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
68 munge!(let Self { encoded } = slot.as_mut());
69
70 match **encoded {
71 0 => (),
72 u32::MAX => {
73 let handle = decoder.take_raw_handle()?;
74 munge!(let Self { mut decoded } = slot);
75 decoded.write(handle);
76 }
77 e => return Err(DecodeError::InvalidHandlePresence(e)),
78 }
79 Ok(())
80 }
81}
82
83#[derive(Debug)]
85#[repr(transparent)]
86pub struct WireOptionalHandle {
87 handle: WireHandle,
88}
89
90unsafe impl Wire for WireOptionalHandle {
91 type Decoded<'de> = Self;
92
93 #[inline]
94 fn zero_padding(out: &mut MaybeUninit<Self>) {
95 munge!(let Self { handle } = out);
96 WireHandle::zero_padding(handle);
97 }
98}
99
100impl WireOptionalHandle {
101 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
103 munge!(let Self { handle } = out);
104 WireHandle::set_encoded_present(handle);
105 }
106
107 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
109 munge!(let Self { handle: WireHandle { encoded } } = out);
110 encoded.write(WireU32(ZX_HANDLE_INVALID));
111 }
112
113 pub fn is_some(&self) -> bool {
115 !self.handle.is_invalid()
116 }
117
118 pub fn is_none(&self) -> bool {
120 self.handle.is_invalid()
121 }
122
123 #[inline]
125 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
126 self.is_some().then(|| self.handle.as_raw_handle())
127 }
128}
129
130unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
131 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
132 munge!(let Self { handle } = slot.as_mut());
133 WireHandle::decode(handle, decoder)
134 }
135}
136
137impl Encodable for Handle {
138 type Encoded = WireHandle;
139}
140
141unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
142 fn encode(
143 self,
144 encoder: &mut E,
145 out: &mut MaybeUninit<Self::Encoded>,
146 ) -> Result<(), EncodeError> {
147 if self.is_invalid() {
148 Err(EncodeError::InvalidRequiredHandle)
149 } else {
150 encoder.push_handle(self)?;
151 WireHandle::set_encoded_present(out);
152 Ok(())
153 }
154 }
155}
156
157impl FromWire<WireHandle> for Handle {
158 fn from_wire(wire: WireHandle) -> Self {
159 let handle = unsafe { Handle::from_raw(wire.as_raw_handle()) };
161 forget(wire);
162 handle
163 }
164}
165
166impl IntoNatural for WireHandle {
167 type Natural = Handle;
168}
169
170impl EncodableOption for Handle {
171 type EncodedOption = WireOptionalHandle;
172}
173
174unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
175 fn encode_option(
176 this: Option<Self>,
177 encoder: &mut E,
178 out: &mut MaybeUninit<Self::EncodedOption>,
179 ) -> Result<(), EncodeError> {
180 if let Some(handle) = this {
181 encoder.push_handle(handle)?;
182 WireOptionalHandle::set_encoded_present(out);
183 } else {
184 WireOptionalHandle::set_encoded_absent(out);
185 }
186 Ok(())
187 }
188}
189
190impl FromWireOption<WireOptionalHandle> for Handle {
191 fn from_wire_option(wire: WireOptionalHandle) -> Option<Self> {
192 let raw_handle = wire.as_raw_handle();
193 forget(wire);
194 raw_handle.map(|raw| unsafe { Handle::from_raw(raw) })
195 }
196}
197
198impl IntoNatural for WireOptionalHandle {
199 type Natural = Option<Handle>;
200}