fidl_next_codec/wire/
result.rs
1use core::fmt;
6use core::marker::PhantomData;
7
8use crate::{
9 munge, Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, Encoder, RawWireUnion,
10 Slot, TakeFrom, ZeroPadding,
11};
12
13#[repr(transparent)]
15pub struct WireResult<T, E> {
16 raw: RawWireUnion,
17 _phantom: PhantomData<(T, E)>,
18}
19
20unsafe impl<T, E> ZeroPadding for WireResult<T, E> {
21 #[inline]
22 unsafe fn zero_padding(ptr: *mut Self) {
23 unsafe {
24 RawWireUnion::zero_padding(ptr.cast());
25 }
26 }
27}
28
29const ORD_OK: u64 = 1;
30const ORD_ERR: u64 = 2;
31
32impl<T, E> WireResult<T, E> {
33 pub fn is_ok(&self) -> bool {
35 self.raw.ordinal() == ORD_OK
36 }
37
38 pub fn is_err(&self) -> bool {
40 self.raw.ordinal() == ORD_ERR
41 }
42
43 pub fn ok(&self) -> Option<&T> {
45 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
46 }
47
48 pub fn err(&self) -> Option<&E> {
50 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
51 }
52
53 pub fn unwrap(&self) -> &T {
57 self.ok().unwrap()
58 }
59
60 pub fn unwrap_err(&self) -> &E {
64 self.err().unwrap()
65 }
66
67 pub fn as_ref(&self) -> Result<&T, &E> {
69 match self.raw.ordinal() {
70 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
71 ORD_ERR => unsafe { Err(self.raw.get().deref_unchecked()) },
72 _ => unsafe { ::core::hint::unreachable_unchecked() },
73 }
74 }
75}
76
77impl<T, E> fmt::Debug for WireResult<T, E>
78where
79 T: fmt::Debug,
80 E: fmt::Debug,
81{
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 self.as_ref().fmt(f)
84 }
85}
86
87unsafe impl<D, T, E> Decode<D> for WireResult<T, E>
88where
89 D: Decoder + ?Sized,
90 T: Decode<D>,
91 E: Decode<D>,
92{
93 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
94 munge!(let Self { mut raw, _phantom: _ } = slot);
95
96 match RawWireUnion::encoded_ordinal(raw.as_mut()) {
97 ORD_OK => RawWireUnion::decode_as::<D, T>(raw, decoder)?,
98 ORD_ERR => RawWireUnion::decode_as::<D, E>(raw, decoder)?,
99 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
100 }
101
102 Ok(())
103 }
104}
105
106impl<T, E> Encodable for Result<T, E>
107where
108 T: Encodable,
109 E: Encodable,
110{
111 type Encoded = WireResult<T::Encoded, E::Encoded>;
112}
113
114impl<Enc, T, E> Encode<Enc> for Result<T, E>
115where
116 Enc: Encoder + ?Sized,
117 T: Encode<Enc>,
118 E: Encode<Enc>,
119{
120 fn encode(
121 &mut self,
122 encoder: &mut Enc,
123 slot: Slot<'_, Self::Encoded>,
124 ) -> Result<(), EncodeError> {
125 munge!(let WireResult { raw, _phantom: _ } = slot);
126
127 match self {
128 Ok(value) => RawWireUnion::encode_as::<Enc, T>(value, ORD_OK, encoder, raw)?,
129 Err(error) => RawWireUnion::encode_as::<Enc, E>(error, ORD_ERR, encoder, raw)?,
130 }
131
132 Ok(())
133 }
134}
135
136impl<T, E, WT, WE> TakeFrom<WireResult<WT, WE>> for Result<T, E>
137where
138 T: TakeFrom<WT>,
139 E: TakeFrom<WE>,
140{
141 fn take_from(from: &WireResult<WT, WE>) -> Self {
142 match from.as_ref() {
143 Ok(value) => Ok(T::take_from(value)),
144 Err(error) => Err(E::take_from(error)),
145 }
146 }
147}