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