fidl_next_codec/fuchsia/
channel.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
5use core::mem::replace;
6
7use crate::fuchsia::{HandleDecoder, HandleEncoder, WireHandle, WireOptionalHandle};
8use crate::{
9    munge, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
10    Slot, TakeFrom, ZeroPadding,
11};
12
13use zx::sys::zx_handle_t;
14use zx::{Channel, Handle};
15
16/// A Zircon channel.
17#[derive(Debug)]
18#[repr(transparent)]
19pub struct WireChannel {
20    handle: WireHandle,
21}
22
23unsafe impl ZeroPadding for WireChannel {
24    #[inline]
25    unsafe fn zero_padding(ptr: *mut Self) {
26        unsafe {
27            WireHandle::zero_padding(ptr.cast());
28        }
29    }
30}
31
32impl WireChannel {
33    /// Encodes a channel as present in a slot.
34    pub fn set_encoded_present(slot: Slot<'_, Self>) {
35        munge!(let Self { handle } = slot);
36        WireHandle::set_encoded_present(handle);
37    }
38
39    /// Returns whether the underlying `zx_handle_t` is invalid.
40    pub fn is_invalid(&self) -> bool {
41        self.handle.is_invalid()
42    }
43
44    /// Takes the channel, if any, leaving an invalid handle in its place.
45    pub fn take(&self) -> Channel {
46        self.handle.take().into()
47    }
48
49    /// Returns the underlying [`zx_handle_t`].
50    #[inline]
51    pub fn as_raw_handle(&self) -> zx_handle_t {
52        self.handle.as_raw_handle()
53    }
54}
55
56unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireChannel {
57    fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
58        munge!(let Self { handle } = slot.as_mut());
59        WireHandle::decode(handle, decoder)
60    }
61}
62
63impl TakeFrom<WireChannel> for Channel {
64    fn take_from(from: &WireChannel) -> Self {
65        from.take()
66    }
67}
68
69/// An optional Zircon channel.
70#[derive(Debug)]
71#[repr(transparent)]
72pub struct WireOptionalChannel {
73    handle: WireOptionalHandle,
74}
75
76unsafe impl ZeroPadding for WireOptionalChannel {
77    #[inline]
78    unsafe fn zero_padding(ptr: *mut Self) {
79        unsafe {
80            WireOptionalHandle::zero_padding(ptr.cast());
81        }
82    }
83}
84
85impl WireOptionalChannel {
86    /// Encodes a channel as present in a slot.
87    pub fn set_encoded_present(slot: Slot<'_, Self>) {
88        munge!(let Self { handle } = slot);
89        WireOptionalHandle::set_encoded_present(handle);
90    }
91
92    /// Encodes a channel as absent in a slot.
93    pub fn set_encoded_absent(slot: Slot<'_, Self>) {
94        munge!(let Self { handle } = slot);
95        WireOptionalHandle::set_encoded_absent(handle);
96    }
97
98    /// Returns whether a channel is present.
99    pub fn is_some(&self) -> bool {
100        !self.handle.is_some()
101    }
102
103    /// Returns whether a channel is absent.
104    pub fn is_none(&self) -> bool {
105        self.handle.is_none()
106    }
107
108    /// Takes the channel, if any, leaving an invalid channel in its place.
109    pub fn take(&self) -> Option<Channel> {
110        self.handle.take().map(Channel::from)
111    }
112
113    /// Returns the underlying [`zx_handle_t`], if any.
114    #[inline]
115    pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
116        self.handle.as_raw_handle()
117    }
118}
119
120impl Encodable for Channel {
121    type Encoded = WireChannel;
122}
123
124impl<E: HandleEncoder + ?Sized> Encode<E> for Channel {
125    fn encode(
126        &mut self,
127        encoder: &mut E,
128        slot: Slot<'_, Self::Encoded>,
129    ) -> Result<(), EncodeError> {
130        let channel = replace(self, Channel::from(Handle::invalid()));
131
132        munge!(let WireChannel { handle } = slot);
133        Handle::from(channel).encode(encoder, handle)
134    }
135}
136
137impl EncodableOption for Channel {
138    type EncodedOption = WireOptionalChannel;
139}
140
141impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Channel {
142    fn encode_option(
143        this: Option<&mut Self>,
144        encoder: &mut E,
145        slot: Slot<'_, Self::EncodedOption>,
146    ) -> Result<(), EncodeError> {
147        let channel = this.map(|channel| replace(channel, Channel::from(Handle::invalid())));
148
149        munge!(let WireOptionalChannel { handle } = slot);
150        Handle::encode_option(channel.map(Handle::from).as_mut(), encoder, handle)
151    }
152}
153
154unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalChannel {
155    fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
156        munge!(let Self { handle } = slot.as_mut());
157        WireOptionalHandle::decode(handle, decoder)
158    }
159}
160
161impl TakeFrom<WireOptionalChannel> for Option<Channel> {
162    fn take_from(from: &WireOptionalChannel) -> Self {
163        from.take()
164    }
165}