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