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
21impl<T, E> Drop for WireResult<'_, T, E> {
22 fn drop(&mut self) {
23 match self.raw.ordinal() {
24 ORD_OK => {
25 let _ = unsafe { self.raw.get().read_unchecked::<T>() };
26 }
27 ORD_ERR => {
28 let _ = unsafe { self.raw.get().read_unchecked::<E>() };
29 }
30 _ => unsafe { ::core::hint::unreachable_unchecked() },
31 }
32 }
33}
34
35unsafe impl<T: Wire, E: Wire> Wire for WireResult<'static, T, E> {
36 type Decoded<'de> = WireResult<'de, T::Decoded<'de>, E::Decoded<'de>>;
37
38 #[inline]
39 fn zero_padding(out: &mut MaybeUninit<Self>) {
40 munge!(let Self { raw, _phantom: _ } = out);
41 RawWireUnion::zero_padding(raw);
42 }
43}
44
45const ORD_OK: u64 = 1;
46const ORD_ERR: u64 = 2;
47
48impl<T, E> WireResult<'_, T, E> {
49 pub fn is_ok(&self) -> bool {
51 self.raw.ordinal() == ORD_OK
52 }
53
54 pub fn is_err(&self) -> bool {
56 self.raw.ordinal() == ORD_ERR
57 }
58
59 pub fn ok(&self) -> Option<&T> {
61 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
62 }
63
64 pub fn err(&self) -> Option<&E> {
66 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
67 }
68
69 pub fn unwrap(&self) -> &T {
73 self.ok().unwrap()
74 }
75
76 pub fn unwrap_err(&self) -> &E {
80 self.err().unwrap()
81 }
82
83 pub fn as_ref(&self) -> Result<&T, &E> {
85 match self.raw.ordinal() {
86 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
87 ORD_ERR => unsafe { Err(self.raw.get().deref_unchecked()) },
88 _ => unsafe { ::core::hint::unreachable_unchecked() },
89 }
90 }
91
92 pub fn into_result(self) -> Result<T, E> {
94 let this = ManuallyDrop::new(self);
95 match this.raw.ordinal() {
96 ORD_OK => unsafe { Ok(this.raw.get().read_unchecked()) },
97 ORD_ERR => unsafe { Err(this.raw.get().read_unchecked()) },
98 _ => unsafe { ::core::hint::unreachable_unchecked() },
99 }
100 }
101}
102
103impl<T: Clone, E: Clone> Clone for WireResult<'_, T, E> {
104 fn clone(&self) -> Self {
105 Self {
106 raw: match self.raw.ordinal() {
107 ORD_OK => unsafe { self.raw.clone_inline_unchecked::<T>() },
108 ORD_ERR => unsafe { self.raw.clone_inline_unchecked::<E>() },
109 _ => unsafe { ::core::hint::unreachable_unchecked() },
110 },
111 _phantom: PhantomData,
112 }
113 }
114}
115
116impl<T, E> fmt::Debug for WireResult<'_, T, E>
117where
118 T: fmt::Debug,
119 E: fmt::Debug,
120{
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 self.as_ref().fmt(f)
123 }
124}
125
126unsafe impl<D, T, E> Decode<D> for WireResult<'static, T, E>
127where
128 D: Decoder + ?Sized,
129 T: Decode<D>,
130 E: Decode<D>,
131{
132 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
133 munge!(let Self { mut raw, _phantom: _ } = slot);
134
135 match RawWireUnion::encoded_ordinal(raw.as_mut()) {
136 ORD_OK => RawWireUnion::decode_as::<D, T>(raw, decoder)?,
137 ORD_ERR => RawWireUnion::decode_as::<D, E>(raw, decoder)?,
138 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
139 }
140
141 Ok(())
142 }
143}
144
145impl<T, E> Encodable for Result<T, E>
146where
147 T: Encodable,
148 E: Encodable,
149{
150 type Encoded = WireResult<'static, T::Encoded, E::Encoded>;
151}
152
153unsafe impl<Enc, T, E> Encode<Enc> for Result<T, E>
154where
155 Enc: Encoder + ?Sized,
156 T: Encode<Enc>,
157 E: Encode<Enc>,
158{
159 fn encode(
160 self,
161 encoder: &mut Enc,
162 out: &mut MaybeUninit<Self::Encoded>,
163 ) -> Result<(), EncodeError> {
164 munge!(let WireResult { raw, _phantom: _ } = out);
165
166 match self {
167 Ok(value) => RawWireUnion::encode_as::<Enc, T>(value, ORD_OK, encoder, raw)?,
168 Err(error) => RawWireUnion::encode_as::<Enc, E>(error, ORD_ERR, encoder, raw)?,
169 }
170
171 Ok(())
172 }
173}
174
175unsafe impl<Enc, T, E> EncodeRef<Enc> for Result<T, E>
176where
177 Enc: Encoder + ?Sized,
178 T: EncodeRef<Enc>,
179 E: EncodeRef<Enc>,
180{
181 fn encode_ref(
182 &self,
183 encoder: &mut Enc,
184 out: &mut MaybeUninit<Self::Encoded>,
185 ) -> Result<(), EncodeError> {
186 self.as_ref().encode(encoder, out)
187 }
188}
189
190impl<T, E, WT, WE> FromWire<WireResult<'_, WT, WE>> for Result<T, E>
191where
192 T: FromWire<WT>,
193 E: FromWire<WE>,
194{
195 #[inline]
196 fn from_wire(wire: WireResult<'_, WT, WE>) -> Self {
197 match wire.into_result() {
198 Ok(value) => Ok(T::from_wire(value)),
199 Err(error) => Err(E::from_wire(error)),
200 }
201 }
202}
203
204impl<T, E, WT, WE> FromWireRef<WireResult<'_, WT, WE>> for Result<T, E>
205where
206 T: FromWireRef<WT>,
207 E: FromWireRef<WE>,
208{
209 #[inline]
210 fn from_wire_ref(wire: &WireResult<'_, WT, WE>) -> Self {
211 match wire.as_ref() {
212 Ok(value) => Ok(T::from_wire_ref(value)),
213 Err(error) => Err(E::from_wire_ref(error)),
214 }
215 }
216}