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, WireResult, ZeroPadding,
11};
12
13use crate::{FrameworkError, WireFrameworkError};
14
15#[derive(Debug)]
17pub enum FlexibleResult<T, E> {
18 Ok(T),
20 Err(E),
22 FrameworkErr(FrameworkError),
24}
25
26#[repr(transparent)]
28pub struct WireFlexibleResult<T, E> {
29 raw: RawWireUnion,
30 _phantom: PhantomData<(T, E)>,
31}
32
33unsafe impl<T, E> ZeroPadding for WireFlexibleResult<T, E> {
34 #[inline]
35 unsafe fn zero_padding(ptr: *mut Self) {
36 unsafe {
37 RawWireUnion::zero_padding(ptr.cast());
38 }
39 }
40}
41
42const ORD_OK: u64 = 1;
43const ORD_ERR: u64 = 2;
44const ORD_FRAMEWORK_ERR: u64 = 3;
45
46impl<T, E> WireFlexibleResult<T, E> {
47 pub fn is_ok(&self) -> bool {
49 self.raw.ordinal() == ORD_OK
50 }
51
52 pub fn is_err(&self) -> bool {
54 self.raw.ordinal() == ORD_ERR
55 }
56
57 pub fn is_framework_err(&self) -> bool {
59 self.raw.ordinal() == ORD_FRAMEWORK_ERR
60 }
61
62 pub fn ok(&self) -> Option<&T> {
64 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
65 }
66
67 pub fn err(&self) -> Option<&E> {
69 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
70 }
71
72 pub fn framework_err(&self) -> Option<FrameworkError> {
74 self.is_framework_err()
75 .then(|| unsafe { (*self.raw.get().deref_unchecked::<WireFrameworkError>()).into() })
76 }
77
78 pub fn unwrap(&self) -> &T {
82 self.ok().unwrap()
83 }
84
85 pub fn unwrap_err(&self) -> &E {
89 self.err().unwrap()
90 }
91
92 pub fn unwrap_framework_err(&self) -> FrameworkError {
96 self.framework_err().unwrap()
97 }
98
99 pub fn as_ref(&self) -> FlexibleResult<&T, &E> {
101 match self.raw.ordinal() {
102 ORD_OK => unsafe { FlexibleResult::Ok(self.raw.get().deref_unchecked()) },
103 ORD_ERR => unsafe { FlexibleResult::Err(self.raw.get().deref_unchecked()) },
104 ORD_FRAMEWORK_ERR => unsafe {
105 FlexibleResult::FrameworkErr(
106 (*self.raw.get().deref_unchecked::<WireFrameworkError>()).into(),
107 )
108 },
109 _ => unsafe { ::core::hint::unreachable_unchecked() },
110 }
111 }
112
113 pub fn as_response(&self) -> Result<&WireResult<T, E>, FrameworkError> {
115 match self.raw.ordinal() {
116 ORD_OK | ORD_ERR => unsafe { Ok(&*(self as *const Self as *const WireResult<T, E>)) },
117 ORD_FRAMEWORK_ERR => unsafe {
118 Err((*self.raw.get().deref_unchecked::<WireFrameworkError>()).into())
119 },
120 _ => unsafe { ::core::hint::unreachable_unchecked() },
121 }
122 }
123
124 pub fn as_result(&self) -> Result<Result<&T, &E>, FrameworkError> {
126 match self.raw.ordinal() {
127 ORD_OK => unsafe { Ok(Ok(self.raw.get().deref_unchecked())) },
128 ORD_ERR => unsafe { Ok(Err(self.raw.get().deref_unchecked())) },
129 ORD_FRAMEWORK_ERR => unsafe {
130 Err((*self.raw.get().deref_unchecked::<WireFrameworkError>()).into())
131 },
132 _ => unsafe { ::core::hint::unreachable_unchecked() },
133 }
134 }
135}
136
137impl<T, E> fmt::Debug for WireFlexibleResult<T, E>
138where
139 T: fmt::Debug,
140 E: fmt::Debug,
141{
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 self.as_ref().fmt(f)
144 }
145}
146
147unsafe impl<D, T, E> Decode<D> for WireFlexibleResult<T, E>
148where
149 D: Decoder + ?Sized,
150 T: Decode<D>,
151 E: Decode<D>,
152{
153 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
154 munge!(let Self { mut raw, _phantom: _ } = slot);
155
156 match RawWireUnion::encoded_ordinal(raw.as_mut()) {
157 ORD_OK => RawWireUnion::decode_as::<D, T>(raw, decoder)?,
158 ORD_ERR => RawWireUnion::decode_as::<D, E>(raw, decoder)?,
159 ORD_FRAMEWORK_ERR => RawWireUnion::decode_as::<D, WireFrameworkError>(raw, decoder)?,
160 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
161 }
162
163 Ok(())
164 }
165}
166
167impl<T, E> Encodable for FlexibleResult<T, E>
168where
169 T: Encodable,
170 E: Encodable,
171{
172 type Encoded = WireFlexibleResult<T::Encoded, E::Encoded>;
173}
174
175impl<Enc, T, E> Encode<Enc> for FlexibleResult<T, E>
176where
177 Enc: Encoder + ?Sized,
178 T: Encode<Enc>,
179 E: Encode<Enc>,
180{
181 fn encode(
182 &mut self,
183 encoder: &mut Enc,
184 slot: Slot<'_, Self::Encoded>,
185 ) -> Result<(), EncodeError> {
186 munge!(let WireFlexibleResult { raw, _phantom: _ } = slot);
187
188 match self {
189 Self::Ok(value) => RawWireUnion::encode_as::<Enc, T>(value, ORD_OK, encoder, raw)?,
190 Self::Err(error) => RawWireUnion::encode_as::<Enc, E>(error, ORD_ERR, encoder, raw)?,
191 Self::FrameworkErr(error) => RawWireUnion::encode_as::<Enc, FrameworkError>(
192 error,
193 ORD_FRAMEWORK_ERR,
194 encoder,
195 raw,
196 )?,
197 }
198
199 Ok(())
200 }
201}
202
203impl<T, WT, E, WE> TakeFrom<WireFlexibleResult<WT, WE>> for FlexibleResult<T, E>
204where
205 T: TakeFrom<WT>,
206 E: TakeFrom<WE>,
207{
208 fn take_from(from: &WireFlexibleResult<WT, WE>) -> Self {
209 match from.as_ref() {
210 FlexibleResult::Ok(value) => Self::Ok(T::take_from(value)),
211 FlexibleResult::Err(error) => Self::Err(E::take_from(error)),
212 FlexibleResult::FrameworkErr(framework_error) => Self::FrameworkErr(framework_error),
213 }
214 }
215}