fidl_next_protocol/
flexible.rs
1use core::fmt;
6use core::marker::PhantomData;
7
8use fidl_next_codec::{
9 munge, Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, Encoder, RawWireUnion,
10 Slot, TakeFrom, ZeroPadding,
11};
12
13use crate::{FrameworkError, WireFrameworkError};
14
15#[derive(Debug)]
17pub enum Flexible<T> {
18 Ok(T),
20 FrameworkErr(FrameworkError),
22}
23
24#[repr(transparent)]
26pub struct WireFlexible<T> {
27 raw: RawWireUnion,
28 _phantom: PhantomData<T>,
29}
30
31unsafe impl<T> ZeroPadding for WireFlexible<T> {
32 #[inline]
33 unsafe fn zero_padding(ptr: *mut Self) {
34 unsafe {
35 RawWireUnion::zero_padding(ptr.cast());
36 }
37 }
38}
39
40const ORD_OK: u64 = 1;
41const ORD_FRAMEWORK_ERR: u64 = 3;
42
43impl<T> WireFlexible<T> {
44 pub fn is_ok(&self) -> bool {
46 self.raw.ordinal() == ORD_OK
47 }
48
49 pub fn is_framework_err(&self) -> bool {
51 self.raw.ordinal() == ORD_FRAMEWORK_ERR
52 }
53
54 pub fn ok(&self) -> Option<&T> {
56 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
57 }
58
59 pub fn framework_err(&self) -> Option<FrameworkError> {
61 self.is_framework_err()
62 .then(|| unsafe { (*self.raw.get().deref_unchecked::<WireFrameworkError>()).into() })
63 }
64
65 pub fn unwrap(&self) -> &T {
69 self.ok().unwrap()
70 }
71
72 pub fn unwrap_framework_err(&self) -> FrameworkError {
76 self.framework_err().unwrap()
77 }
78
79 pub fn as_ref(&self) -> Flexible<&T> {
81 match self.raw.ordinal() {
82 ORD_OK => unsafe { Flexible::Ok(self.raw.get().deref_unchecked()) },
83 ORD_FRAMEWORK_ERR => unsafe {
84 Flexible::FrameworkErr(
85 (*self.raw.get().deref_unchecked::<WireFrameworkError>()).into(),
86 )
87 },
88 _ => unsafe { ::core::hint::unreachable_unchecked() },
89 }
90 }
91
92 pub fn as_result(&self) -> Result<&T, FrameworkError> {
94 match self.raw.ordinal() {
95 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
96 ORD_FRAMEWORK_ERR => unsafe {
97 Err((*self.raw.get().deref_unchecked::<WireFrameworkError>()).into())
98 },
99 _ => unsafe { ::core::hint::unreachable_unchecked() },
100 }
101 }
102}
103
104impl<T> fmt::Debug for WireFlexible<T>
105where
106 T: fmt::Debug,
107{
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 self.as_ref().fmt(f)
110 }
111}
112
113unsafe impl<D, T> Decode<D> for WireFlexible<T>
114where
115 D: Decoder + ?Sized,
116 T: Decode<D>,
117{
118 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
119 munge!(let Self { mut raw, _phantom: _ } = slot);
120
121 match RawWireUnion::encoded_ordinal(raw.as_mut()) {
122 ORD_OK => RawWireUnion::decode_as::<D, T>(raw, decoder)?,
123 ORD_FRAMEWORK_ERR => RawWireUnion::decode_as::<D, WireFrameworkError>(raw, decoder)?,
124 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
125 }
126
127 Ok(())
128 }
129}
130
131impl<T> Encodable for Flexible<T>
132where
133 T: Encodable,
134{
135 type Encoded = WireFlexible<T::Encoded>;
136}
137
138impl<E, T> Encode<E> for Flexible<T>
139where
140 E: Encoder + ?Sized,
141 T: Encode<E>,
142{
143 fn encode(
144 &mut self,
145 encoder: &mut E,
146 slot: Slot<'_, Self::Encoded>,
147 ) -> Result<(), EncodeError> {
148 munge!(let WireFlexible { raw, _phantom: _ } = slot);
149
150 match self {
151 Self::Ok(value) => RawWireUnion::encode_as::<E, T>(value, ORD_OK, encoder, raw)?,
152 Self::FrameworkErr(error) => RawWireUnion::encode_as::<E, FrameworkError>(
153 error,
154 ORD_FRAMEWORK_ERR,
155 encoder,
156 raw,
157 )?,
158 }
159
160 Ok(())
161 }
162}
163
164impl<T, WT> TakeFrom<WireFlexible<WT>> for Flexible<T>
165where
166 T: TakeFrom<WT>,
167{
168 fn take_from(from: &WireFlexible<WT>) -> Self {
169 match from.as_ref() {
170 Flexible::Ok(value) => Self::Ok(T::take_from(value)),
171 Flexible::FrameworkErr(framework_error) => Self::FrameworkErr(framework_error),
172 }
173 }
174}