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, Slot, ValidationError, Wire, munge, wire,
12};
13
14use core::result::Result as CoreResult;
15
16#[repr(transparent)]
18pub struct Result<'de, T, E> {
19 raw: wire::Union,
20 _phantom: PhantomData<(&'de mut [Chunk], T, E)>,
21}
22
23impl<T, E> Drop for Result<'_, T, E> {
24 fn drop(&mut self) {
25 match self.raw.ordinal() {
26 ORD_OK => {
27 let _ = unsafe { self.raw.get().read_unchecked::<T>() };
30 }
31 ORD_ERR => {
32 let _ = unsafe { self.raw.get().read_unchecked::<E>() };
35 }
36 _ => unsafe { ::core::hint::unreachable_unchecked() },
38 }
39 }
40}
41
42impl<T, E> Constrained for Result<'_, T, E>
43where
44 T: Constrained<Constraint = ()>,
45 E: Constrained<Constraint = ()>,
46{
47 type Constraint = ();
48
49 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> CoreResult<(), ValidationError> {
50 Ok(())
51 }
52}
53
54unsafe impl<T, E> Wire for Result<'static, T, E>
57where
58 T: Wire<Constraint = ()>,
59 E: Wire<Constraint = ()>,
60{
61 type Narrowed<'de> = Result<'de, T::Narrowed<'de>, E::Narrowed<'de>>;
62
63 #[inline]
64 fn zero_padding(out: &mut MaybeUninit<Self>) {
65 munge!(let Self { raw, _phantom: _ } = out);
66 wire::Union::zero_padding(raw);
67 }
68}
69
70const ORD_OK: u64 = 1;
71const ORD_ERR: u64 = 2;
72
73impl<T, E> Result<'_, T, E> {
74 pub fn is_ok(&self) -> bool {
76 self.raw.ordinal() == ORD_OK
77 }
78
79 pub fn is_err(&self) -> bool {
81 self.raw.ordinal() == ORD_ERR
82 }
83
84 pub fn ok(&self) -> Option<&T> {
86 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
88 }
89
90 pub fn err(&self) -> Option<&E> {
92 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
94 }
95
96 pub fn unwrap(&self) -> &T {
100 self.ok().unwrap()
101 }
102
103 pub fn unwrap_err(&self) -> &E {
107 self.err().unwrap()
108 }
109
110 pub fn as_ref(&self) -> CoreResult<&T, &E> {
112 match self.raw.ordinal() {
113 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
115 ORD_ERR => unsafe { Err(self.raw.get().deref_unchecked()) },
117 _ => unsafe { ::core::hint::unreachable_unchecked() },
119 }
120 }
121
122 pub fn into_result(self) -> CoreResult<T, E> {
124 let this = ManuallyDrop::new(self);
125 match this.raw.ordinal() {
126 ORD_OK => unsafe { Ok(this.raw.get().read_unchecked()) },
129 ORD_ERR => unsafe { Err(this.raw.get().read_unchecked()) },
132 _ => unsafe { ::core::hint::unreachable_unchecked() },
134 }
135 }
136}
137
138impl<T: Clone, E: Clone> Clone for Result<'_, T, E> {
139 fn clone(&self) -> Self {
140 Self {
141 raw: match self.raw.ordinal() {
142 ORD_OK => unsafe { self.raw.clone_inline_unchecked::<T>() },
144 ORD_ERR => unsafe { self.raw.clone_inline_unchecked::<E>() },
146 _ => unsafe { ::core::hint::unreachable_unchecked() },
149 },
150 _phantom: PhantomData,
151 }
152 }
153}
154
155impl<T, E> fmt::Debug for Result<'_, T, E>
156where
157 T: fmt::Debug,
158 E: fmt::Debug,
159{
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 self.as_ref().fmt(f)
162 }
163}
164
165unsafe impl<'de, D, T, E> Decode<D> for Result<'de, T, E>
168where
169 D: Decoder<'de> + ?Sized,
170 T: Decode<D, Constraint = ()>,
171 E: Decode<D, Constraint = ()>,
172{
173 fn decode(slot: Slot<'_, Self>, decoder: &mut D, _: ()) -> CoreResult<(), DecodeError> {
174 munge!(let Self { mut raw, _phantom: _ } = slot);
175
176 match wire::Union::encoded_ordinal(raw.as_mut()) {
177 ORD_OK => wire::Union::decode_as::<D, T>(raw, decoder, ())?,
178 ORD_ERR => wire::Union::decode_as::<D, E>(raw, decoder, ())?,
179 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
180 }
181
182 Ok(())
183 }
184}
185
186unsafe impl<Enc, WT, T, WE, E> Encode<Result<'static, WT, WE>, Enc> for CoreResult<T, E>
190where
191 Enc: Encoder + ?Sized,
192 WT: Wire<Constraint = ()>,
193 T: Encode<WT, Enc>,
194 WE: Wire<Constraint = ()>,
195 E: Encode<WE, Enc>,
196{
197 fn encode(
198 self,
199 encoder: &mut Enc,
200 out: &mut MaybeUninit<Result<'static, WT, WE>>,
201 _: (),
202 ) -> CoreResult<(), EncodeError> {
203 munge!(let Result { raw, _phantom: _ } = out);
204
205 match self {
206 Ok(value) => wire::Union::encode_as::<Enc, WT>(value, ORD_OK, encoder, raw, ())?,
207 Err(error) => wire::Union::encode_as::<Enc, WE>(error, ORD_ERR, encoder, raw, ())?,
208 }
209
210 Ok(())
211 }
212}
213
214unsafe impl<'a, Enc, WT, T, WE, E> Encode<Result<'static, WT, WE>, Enc> for &'a CoreResult<T, E>
216where
217 Enc: Encoder + ?Sized,
218 WT: Wire<Constraint = ()>,
219 &'a T: Encode<WT, Enc>,
220 WE: Wire<Constraint = ()>,
221 &'a E: Encode<WE, Enc>,
222{
223 fn encode(
224 self,
225 encoder: &mut Enc,
226 out: &mut MaybeUninit<Result<'static, WT, WE>>,
227 _: (),
228 ) -> CoreResult<(), EncodeError> {
229 self.as_ref().encode(encoder, out, ())
230 }
231}
232
233impl<T, E, WT, WE> FromWire<Result<'_, WT, WE>> for CoreResult<T, E>
234where
235 T: FromWire<WT>,
236 E: FromWire<WE>,
237{
238 #[inline]
239 fn from_wire(wire: Result<'_, WT, WE>) -> Self {
240 match wire.into_result() {
241 Ok(value) => Ok(T::from_wire(value)),
242 Err(error) => Err(E::from_wire(error)),
243 }
244 }
245}
246
247impl<T: IntoNatural, E: IntoNatural> IntoNatural for Result<'_, T, E> {
248 type Natural = CoreResult<T::Natural, E::Natural>;
249}
250
251impl<T, E, WT, WE> FromWireRef<Result<'_, WT, WE>> for CoreResult<T, E>
252where
253 T: FromWireRef<WT>,
254 E: FromWireRef<WE>,
255{
256 #[inline]
257 fn from_wire_ref(wire: &Result<'_, WT, WE>) -> Self {
258 match wire.as_ref() {
259 Ok(value) => Ok(T::from_wire_ref(value)),
260 Err(error) => Err(E::from_wire_ref(error)),
261 }
262 }
263}
264
265#[cfg(test)]
266mod tests {
267 use crate::{DecoderExt as _, EncoderExt as _, chunks, wire};
268
269 #[test]
270 fn encode_result() {
271 assert_eq!(
272 Vec::encode(Result::<i32, i32>::Ok(0x12345678)).unwrap(),
273 chunks![
274 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
275 0x01, 0x00,
276 ],
277 );
278 assert_eq!(
279 Vec::encode(Result::<i32, i32>::Err(0x12345678)).unwrap(),
280 chunks![
281 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
282 0x01, 0x00,
283 ],
284 );
285 }
286
287 #[test]
288 fn decode_result() {
289 assert_eq!(
290 chunks![
291 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
292 0x01, 0x00,
293 ]
294 .as_mut_slice()
295 .decode::<wire::Result<'_, wire::Int32, wire::Int32>>()
296 .unwrap()
297 .as_ref()
298 .unwrap()
299 .0,
300 0x12345678,
301 );
302 assert_eq!(
303 chunks![
304 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
305 0x01, 0x00,
306 ]
307 .as_mut_slice()
308 .decode::<wire::Result<'_, wire::Int32, wire::Int32>>()
309 .unwrap()
310 .as_ref()
311 .unwrap_err()
312 .0,
313 0x12345678,
314 );
315 }
316}