1use core::fmt;
6use core::marker::PhantomData;
7use core::mem::{ManuallyDrop, MaybeUninit};
8
9use crate::{
10 munge, Chunk, Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, EncodeRef, Encoder,
11 FromWire, FromWireRef, RawWireUnion, Slot, Wire,
12};
13
14#[repr(transparent)]
16pub struct WireResult<'de, T, E> {
17 raw: RawWireUnion,
18 _phantom: PhantomData<(&'de mut [Chunk], T, E)>,
19}
20
21unsafe impl<T: Wire, E: Wire> Wire for WireResult<'static, T, E> {
22 type Decoded<'de> = WireResult<'de, T::Decoded<'de>, E::Decoded<'de>>;
23
24 #[inline]
25 fn zero_padding(out: &mut MaybeUninit<Self>) {
26 munge!(let Self { raw, _phantom: _ } = out);
27 RawWireUnion::zero_padding(raw);
28 }
29}
30
31const ORD_OK: u64 = 1;
32const ORD_ERR: u64 = 2;
33
34impl<T, E> WireResult<'_, T, E> {
35 pub fn is_ok(&self) -> bool {
37 self.raw.ordinal() == ORD_OK
38 }
39
40 pub fn is_err(&self) -> bool {
42 self.raw.ordinal() == ORD_ERR
43 }
44
45 pub fn ok(&self) -> Option<&T> {
47 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
48 }
49
50 pub fn err(&self) -> Option<&E> {
52 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
53 }
54
55 pub fn unwrap(&self) -> &T {
59 self.ok().unwrap()
60 }
61
62 pub fn unwrap_err(&self) -> &E {
66 self.err().unwrap()
67 }
68
69 pub fn as_ref(&self) -> Result<&T, &E> {
71 match self.raw.ordinal() {
72 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
73 ORD_ERR => unsafe { Err(self.raw.get().deref_unchecked()) },
74 _ => unsafe { ::core::hint::unreachable_unchecked() },
75 }
76 }
77
78 pub fn into_result(self) -> Result<T, E> {
80 let raw = ManuallyDrop::new(self.raw);
81 match raw.ordinal() {
82 ORD_OK => unsafe { Ok(raw.get().read_unchecked()) },
83 ORD_ERR => unsafe { Err(raw.get().read_unchecked()) },
84 _ => unsafe { ::core::hint::unreachable_unchecked() },
85 }
86 }
87}
88
89impl<T, E> fmt::Debug for WireResult<'_, T, E>
90where
91 T: fmt::Debug,
92 E: fmt::Debug,
93{
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 self.as_ref().fmt(f)
96 }
97}
98
99unsafe impl<D, T, E> Decode<D> for WireResult<'static, T, E>
100where
101 D: Decoder + ?Sized,
102 T: Decode<D>,
103 E: Decode<D>,
104{
105 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
106 munge!(let Self { mut raw, _phantom: _ } = slot);
107
108 match RawWireUnion::encoded_ordinal(raw.as_mut()) {
109 ORD_OK => RawWireUnion::decode_as::<D, T>(raw, decoder)?,
110 ORD_ERR => RawWireUnion::decode_as::<D, E>(raw, decoder)?,
111 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
112 }
113
114 Ok(())
115 }
116}
117
118impl<T, E> Encodable for Result<T, E>
119where
120 T: Encodable,
121 E: Encodable,
122{
123 type Encoded = WireResult<'static, T::Encoded, E::Encoded>;
124}
125
126unsafe impl<Enc, T, E> Encode<Enc> for Result<T, E>
127where
128 Enc: Encoder + ?Sized,
129 T: Encode<Enc>,
130 E: Encode<Enc>,
131{
132 fn encode(
133 self,
134 encoder: &mut Enc,
135 out: &mut MaybeUninit<Self::Encoded>,
136 ) -> Result<(), EncodeError> {
137 munge!(let WireResult { raw, _phantom: _ } = out);
138
139 match self {
140 Ok(value) => RawWireUnion::encode_as::<Enc, T>(value, ORD_OK, encoder, raw)?,
141 Err(error) => RawWireUnion::encode_as::<Enc, E>(error, ORD_ERR, encoder, raw)?,
142 }
143
144 Ok(())
145 }
146}
147
148unsafe impl<Enc, T, E> EncodeRef<Enc> for Result<T, E>
149where
150 Enc: Encoder + ?Sized,
151 T: EncodeRef<Enc>,
152 E: EncodeRef<Enc>,
153{
154 fn encode_ref(
155 &self,
156 encoder: &mut Enc,
157 out: &mut MaybeUninit<Self::Encoded>,
158 ) -> Result<(), EncodeError> {
159 self.as_ref().encode(encoder, out)
160 }
161}
162
163impl<T, E, WT, WE> FromWire<WireResult<'_, WT, WE>> for Result<T, E>
164where
165 T: FromWire<WT>,
166 E: FromWire<WE>,
167{
168 #[inline]
169 fn from_wire(wire: WireResult<'_, WT, WE>) -> Self {
170 match wire.into_result() {
171 Ok(value) => Ok(T::from_wire(value)),
172 Err(error) => Err(E::from_wire(error)),
173 }
174 }
175}
176
177impl<T, E, WT, WE> FromWireRef<WireResult<'_, WT, WE>> for Result<T, E>
178where
179 T: FromWireRef<WT>,
180 E: FromWireRef<WE>,
181{
182 #[inline]
183 fn from_wire_ref(wire: &WireResult<'_, WT, WE>) -> Self {
184 match wire.as_ref() {
185 Ok(value) => Ok(T::from_wire_ref(value)),
186 Err(error) => Err(E::from_wire_ref(error)),
187 }
188 }
189}