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