fidl_next_codec/wire/
union.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 munge::munge;
6
7use crate::decoder::InternalHandleDecoder;
8use crate::encoder::InternalHandleEncoder;
9use crate::{
10    Decode, DecodeError, Decoder, Encode, EncodeError, Encoder, Slot, WireEnvelope, WireU64,
11    ZeroPadding,
12};
13
14/// A raw FIDL union
15#[repr(C)]
16pub struct RawWireUnion {
17    ordinal: WireU64,
18    envelope: WireEnvelope,
19}
20
21unsafe impl ZeroPadding for RawWireUnion {
22    #[inline]
23    unsafe fn zero_padding(_: *mut Self) {
24        // Wire unions have no padding
25    }
26}
27
28impl RawWireUnion {
29    /// Encodes that a union is absent in a slot.
30    #[inline]
31    pub fn encode_absent(slot: Slot<'_, Self>) {
32        munge!(let Self { mut ordinal, envelope } = slot);
33
34        **ordinal = 0;
35        WireEnvelope::encode_zero(envelope);
36    }
37
38    /// Encodes a `'static` value and ordinal in a slot.
39    #[inline]
40    pub fn encode_as_static<E: InternalHandleEncoder + ?Sized, T: Encode<E>>(
41        value: &mut T,
42        ord: u64,
43        encoder: &mut E,
44        slot: Slot<'_, Self>,
45    ) -> Result<(), EncodeError> {
46        munge!(let Self { mut ordinal, envelope } = slot);
47
48        **ordinal = ord;
49        WireEnvelope::encode_value_static(value, encoder, envelope)
50    }
51
52    /// Encodes a value and ordinal in a slot.
53    #[inline]
54    pub fn encode_as<E: Encoder + ?Sized, T: Encode<E>>(
55        value: &mut T,
56        ord: u64,
57        encoder: &mut E,
58        slot: Slot<'_, Self>,
59    ) -> Result<(), EncodeError> {
60        munge!(let Self { mut ordinal, envelope } = slot);
61
62        **ordinal = ord;
63        WireEnvelope::encode_value(value, encoder, envelope)
64    }
65
66    /// Returns the ordinal of the encoded value.
67    #[inline]
68    pub fn encoded_ordinal(slot: Slot<'_, Self>) -> u64 {
69        munge!(let Self { ordinal, envelope: _ } = slot);
70        **ordinal
71    }
72
73    /// Decodes an absent union from a slot.
74    #[inline]
75    pub fn decode_absent(slot: Slot<'_, Self>) -> Result<(), DecodeError> {
76        munge!(let Self { ordinal: _, envelope } = slot);
77        if !WireEnvelope::is_encoded_zero(envelope) {
78            return Err(DecodeError::InvalidUnionEnvelope);
79        }
80        Ok(())
81    }
82
83    /// Decodes an unknown `'static` value from a union.
84    ///
85    /// The handles owned by the unknown value are discarded.
86    #[inline]
87    pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
88        slot: Slot<'_, Self>,
89        decoder: &mut D,
90    ) -> Result<(), DecodeError> {
91        munge!(let Self { ordinal: _, envelope } = slot);
92        WireEnvelope::decode_unknown_static(envelope, decoder)
93    }
94
95    /// Decodes an unknown value from a union.
96    ///
97    /// The handles owned by the unknown value are discarded.
98    #[inline]
99    pub fn decode_unknown<D: Decoder + ?Sized>(
100        slot: Slot<'_, Self>,
101        decoder: &mut D,
102    ) -> Result<(), DecodeError> {
103        munge!(let Self { ordinal: _, envelope } = slot);
104        WireEnvelope::decode_unknown(envelope, decoder)
105    }
106
107    /// Decodes the typed `'static` value in a union.
108    #[inline]
109    pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
110        slot: Slot<'_, Self>,
111        decoder: &mut D,
112    ) -> Result<(), DecodeError> {
113        munge!(let Self { ordinal: _, envelope } = slot);
114        WireEnvelope::decode_as_static::<D, T>(envelope, decoder)
115    }
116
117    /// Decodes the typed value in a union.
118    #[inline]
119    pub fn decode_as<D: Decoder + ?Sized, T: Decode<D>>(
120        slot: Slot<'_, Self>,
121        decoder: &mut D,
122    ) -> Result<(), DecodeError> {
123        munge!(let Self { ordinal: _, envelope } = slot);
124        WireEnvelope::decode_as::<D, T>(envelope, decoder)
125    }
126
127    /// The absent optional union.
128    #[inline]
129    pub fn absent() -> Self {
130        Self { ordinal: WireU64(0), envelope: WireEnvelope::zero() }
131    }
132
133    /// Returns whether the union contains a value.
134    #[inline]
135    pub fn is_some(&self) -> bool {
136        *self.ordinal != 0
137    }
138
139    /// Returns whether the union is empty.
140    #[inline]
141    pub fn is_none(&self) -> bool {
142        !self.is_some()
143    }
144
145    /// Returns the ordinal of the union.
146    #[inline]
147    pub fn ordinal(&self) -> u64 {
148        *self.ordinal
149    }
150
151    /// Gets a reference to the envelope underlying the union.
152    #[inline]
153    pub fn get(&self) -> &WireEnvelope {
154        &self.envelope
155    }
156
157    /// Clones the union, assuming that it contains an inline `T`.
158    ///
159    /// # Safety
160    ///
161    /// The union must have been successfully decoded as a `T`.
162    #[inline]
163    pub unsafe fn clone_unchecked<T: Clone>(&self) -> Self {
164        Self { ordinal: self.ordinal, envelope: unsafe { self.envelope.clone_unchecked::<T>() } }
165    }
166}