radicle_std_ext/
ops.rs

1// Copyright © 2021 The Radicle Link Contributors
2//
3// This file is part of radicle-link, distributed under the GPLv3 with Radicle
4// Linking Exception. For full terms see the included LICENSE file.
5
6//! Provides Try-trait for stable rust
7//!
8//! Probably doesn't work with `?`-desugaring. If the `nightly` feature is
9//! enabled for this crate, the `std` version is enabled.
10
11#[cfg(not(feature = "nightly"))]
12pub use stable::{FromResidual, Try};
13#[cfg(feature = "nightly")]
14pub use std::ops::{FromResidual, Try};
15
16mod stable {
17    use std::{convert, ops::ControlFlow, task::Poll};
18
19    pub trait Try: FromResidual {
20        type Output;
21        type Residual;
22
23        fn from_output(output: Self::Output) -> Self;
24        fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
25    }
26
27    pub trait FromResidual<R = <Self as Try>::Residual> {
28        fn from_residual(residual: R) -> Self;
29    }
30
31    impl<B, C> Try for ControlFlow<B, C> {
32        type Output = C;
33        type Residual = ControlFlow<B, convert::Infallible>;
34
35        #[inline]
36        fn from_output(output: Self::Output) -> Self {
37            ControlFlow::Continue(output)
38        }
39
40        #[inline]
41        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
42            match self {
43                ControlFlow::Continue(c) => ControlFlow::Continue(c),
44                ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
45            }
46        }
47    }
48
49    impl<B, C> FromResidual for ControlFlow<B, C> {
50        #[inline]
51        fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
52            match residual {
53                ControlFlow::Break(b) => ControlFlow::Break(b),
54                _ => unreachable!(),
55            }
56        }
57    }
58
59    impl<T> Try for Option<T> {
60        type Output = T;
61        type Residual = Option<convert::Infallible>;
62
63        #[inline]
64        fn from_output(output: Self::Output) -> Self {
65            Some(output)
66        }
67
68        #[inline]
69        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
70            match self {
71                Some(v) => ControlFlow::Continue(v),
72                None => ControlFlow::Break(None),
73            }
74        }
75    }
76
77    impl<T> FromResidual for Option<T> {
78        #[inline]
79        fn from_residual(residual: Option<convert::Infallible>) -> Self {
80            match residual {
81                None => None,
82                _ => unreachable!(),
83            }
84        }
85    }
86
87    impl<T, E> Try for Result<T, E> {
88        type Output = T;
89        type Residual = Result<convert::Infallible, E>;
90
91        #[inline]
92        fn from_output(output: Self::Output) -> Self {
93            Ok(output)
94        }
95
96        #[inline]
97        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
98            match self {
99                Ok(v) => ControlFlow::Continue(v),
100                Err(e) => ControlFlow::Break(Err(e)),
101            }
102        }
103    }
104
105    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Result<T, F> {
106        #[inline]
107        fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
108            match residual {
109                Err(e) => Err(From::from(e)),
110                _ => unreachable!(),
111            }
112        }
113    }
114
115    impl<T, E> Try for Poll<Option<Result<T, E>>> {
116        type Output = Poll<Option<T>>;
117        type Residual = Result<convert::Infallible, E>;
118
119        #[inline]
120        fn from_output(c: Self::Output) -> Self {
121            c.map(|x| x.map(Ok))
122        }
123
124        #[inline]
125        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
126            match self {
127                Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
128                Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
129                Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
130                Poll::Pending => ControlFlow::Continue(Poll::Pending),
131            }
132        }
133    }
134
135    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Option<Result<T, F>>> {
136        #[inline]
137        fn from_residual(x: Result<convert::Infallible, E>) -> Self {
138            match x {
139                Err(e) => Poll::Ready(Some(Err(From::from(e)))),
140                _ => unreachable!(),
141            }
142        }
143    }
144
145    impl<T, E> Try for Poll<Result<T, E>> {
146        type Output = Poll<T>;
147        type Residual = Result<convert::Infallible, E>;
148
149        #[inline]
150        fn from_output(c: Self::Output) -> Self {
151            c.map(Ok)
152        }
153
154        #[inline]
155        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
156            match self {
157                Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
158                Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
159                Poll::Pending => ControlFlow::Continue(Poll::Pending),
160            }
161        }
162    }
163
164    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
165        #[inline]
166        fn from_residual(x: Result<convert::Infallible, E>) -> Self {
167            match x {
168                Err(e) => Poll::Ready(Err(From::from(e))),
169                _ => unreachable!(),
170            }
171        }
172    }
173}