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>() };
28 }
29 ORD_ERR => {
30 let _ = unsafe { self.raw.get().read_unchecked::<E>() };
31 }
32 _ => unsafe { ::core::hint::unreachable_unchecked() },
33 }
34 }
35}
36
37impl<T, E> Constrained for Result<'_, T, E>
38where
39 T: Constrained<Constraint = ()>,
40 E: Constrained<Constraint = ()>,
41{
42 type Constraint = ();
43
44 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> CoreResult<(), ValidationError> {
45 Ok(())
46 }
47}
48
49unsafe impl<T, E> Wire for Result<'static, T, E>
50where
51 T: Wire<Constraint = ()>,
52 E: Wire<Constraint = ()>,
53{
54 type Narrowed<'de> = Result<'de, T::Narrowed<'de>, E::Narrowed<'de>>;
55
56 #[inline]
57 fn zero_padding(out: &mut MaybeUninit<Self>) {
58 munge!(let Self { raw, _phantom: _ } = out);
59 wire::Union::zero_padding(raw);
60 }
61}
62
63const ORD_OK: u64 = 1;
64const ORD_ERR: u64 = 2;
65
66impl<T, E> Result<'_, T, E> {
67 pub fn is_ok(&self) -> bool {
69 self.raw.ordinal() == ORD_OK
70 }
71
72 pub fn is_err(&self) -> bool {
74 self.raw.ordinal() == ORD_ERR
75 }
76
77 pub fn ok(&self) -> Option<&T> {
79 self.is_ok().then(|| unsafe { self.raw.get().deref_unchecked() })
80 }
81
82 pub fn err(&self) -> Option<&E> {
84 self.is_err().then(|| unsafe { self.raw.get().deref_unchecked() })
85 }
86
87 pub fn unwrap(&self) -> &T {
91 self.ok().unwrap()
92 }
93
94 pub fn unwrap_err(&self) -> &E {
98 self.err().unwrap()
99 }
100
101 pub fn as_ref(&self) -> CoreResult<&T, &E> {
103 match self.raw.ordinal() {
104 ORD_OK => unsafe { Ok(self.raw.get().deref_unchecked()) },
105 ORD_ERR => unsafe { Err(self.raw.get().deref_unchecked()) },
106 _ => unsafe { ::core::hint::unreachable_unchecked() },
107 }
108 }
109
110 pub fn into_result(self) -> CoreResult<T, E> {
112 let this = ManuallyDrop::new(self);
113 match this.raw.ordinal() {
114 ORD_OK => unsafe { Ok(this.raw.get().read_unchecked()) },
115 ORD_ERR => unsafe { Err(this.raw.get().read_unchecked()) },
116 _ => unsafe { ::core::hint::unreachable_unchecked() },
117 }
118 }
119}
120
121impl<T: Clone, E: Clone> Clone for Result<'_, T, E> {
122 fn clone(&self) -> Self {
123 Self {
124 raw: match self.raw.ordinal() {
125 ORD_OK => unsafe { self.raw.clone_inline_unchecked::<T>() },
126 ORD_ERR => unsafe { self.raw.clone_inline_unchecked::<E>() },
127 _ => unsafe { ::core::hint::unreachable_unchecked() },
128 },
129 _phantom: PhantomData,
130 }
131 }
132}
133
134impl<T, E> fmt::Debug for Result<'_, T, E>
135where
136 T: fmt::Debug,
137 E: fmt::Debug,
138{
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 self.as_ref().fmt(f)
141 }
142}
143
144unsafe impl<'de, D, T, E> Decode<D> for Result<'de, T, E>
145where
146 D: Decoder<'de> + ?Sized,
147 T: Decode<D, Constraint = ()>,
148 E: Decode<D, Constraint = ()>,
149{
150 fn decode(slot: Slot<'_, Self>, decoder: &mut D, _: ()) -> CoreResult<(), DecodeError> {
151 munge!(let Self { mut raw, _phantom: _ } = slot);
152
153 match wire::Union::encoded_ordinal(raw.as_mut()) {
154 ORD_OK => wire::Union::decode_as::<D, T>(raw, decoder, ())?,
155 ORD_ERR => wire::Union::decode_as::<D, E>(raw, decoder, ())?,
156 ord => return Err(DecodeError::InvalidUnionOrdinal(ord as usize)),
157 }
158
159 Ok(())
160 }
161}
162
163unsafe impl<Enc, WT, T, WE, E> Encode<Result<'static, WT, WE>, Enc> for CoreResult<T, E>
164where
165 Enc: Encoder + ?Sized,
166 WT: Wire<Constraint = ()>,
167 T: Encode<WT, Enc>,
168 WE: Wire<Constraint = ()>,
169 E: Encode<WE, Enc>,
170{
171 fn encode(
172 self,
173 encoder: &mut Enc,
174 out: &mut MaybeUninit<Result<'_, WT, WE>>,
175 _: (),
176 ) -> CoreResult<(), EncodeError> {
177 munge!(let Result { raw, _phantom: _ } = out);
178
179 match self {
180 Ok(value) => wire::Union::encode_as::<Enc, WT>(value, ORD_OK, encoder, raw, ())?,
181 Err(error) => wire::Union::encode_as::<Enc, WE>(error, ORD_ERR, encoder, raw, ())?,
182 }
183
184 Ok(())
185 }
186}
187
188unsafe impl<'a, Enc, WT, T, WE, E> Encode<Result<'static, WT, WE>, Enc> for &'a CoreResult<T, E>
189where
190 Enc: Encoder + ?Sized,
191 WT: Wire<Constraint = ()>,
192 &'a T: Encode<WT, Enc>,
193 WE: Wire<Constraint = ()>,
194 &'a E: Encode<WE, Enc>,
195{
196 fn encode(
197 self,
198 encoder: &mut Enc,
199 out: &mut MaybeUninit<Result<'static, WT, WE>>,
200 _: (),
201 ) -> CoreResult<(), EncodeError> {
202 self.as_ref().encode(encoder, out, ())
203 }
204}
205
206impl<T, E, WT, WE> FromWire<Result<'_, WT, WE>> for CoreResult<T, E>
207where
208 T: FromWire<WT>,
209 E: FromWire<WE>,
210{
211 #[inline]
212 fn from_wire(wire: Result<'_, WT, WE>) -> Self {
213 match wire.into_result() {
214 Ok(value) => Ok(T::from_wire(value)),
215 Err(error) => Err(E::from_wire(error)),
216 }
217 }
218}
219
220impl<T: IntoNatural, E: IntoNatural> IntoNatural for Result<'_, T, E> {
221 type Natural = CoreResult<T::Natural, E::Natural>;
222}
223
224impl<T, E, WT, WE> FromWireRef<Result<'_, WT, WE>> for CoreResult<T, E>
225where
226 T: FromWireRef<WT>,
227 E: FromWireRef<WE>,
228{
229 #[inline]
230 fn from_wire_ref(wire: &Result<'_, WT, WE>) -> Self {
231 match wire.as_ref() {
232 Ok(value) => Ok(T::from_wire_ref(value)),
233 Err(error) => Err(E::from_wire_ref(error)),
234 }
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use crate::{DecoderExt as _, EncoderExt as _, chunks, wire};
241
242 #[test]
243 fn encode_result() {
244 assert_eq!(
245 Vec::encode(Result::<i32, i32>::Ok(0x12345678)).unwrap(),
246 chunks![
247 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
248 0x01, 0x00,
249 ],
250 );
251 assert_eq!(
252 Vec::encode(Result::<i32, i32>::Err(0x12345678)).unwrap(),
253 chunks![
254 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
255 0x01, 0x00,
256 ],
257 );
258 }
259
260 #[test]
261 fn decode_result() {
262 assert_eq!(
263 chunks![
264 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
265 0x01, 0x00,
266 ]
267 .as_mut_slice()
268 .decode::<wire::Result<'_, wire::Int32, wire::Int32>>()
269 .unwrap()
270 .as_ref()
271 .unwrap()
272 .0,
273 0x12345678,
274 );
275 assert_eq!(
276 chunks![
277 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
278 0x01, 0x00,
279 ]
280 .as_mut_slice()
281 .decode::<wire::Result<'_, wire::Int32, wire::Int32>>()
282 .unwrap()
283 .as_ref()
284 .unwrap_err()
285 .0,
286 0x12345678,
287 );
288 }
289}