// Copyright © 2021 The Radicle Link Contributors // // This file is part of radicle-link, distributed under the GPLv3 with Radicle // Linking Exception. For full terms see the included LICENSE file. //! Provides Try-trait for stable rust //! //! Probably doesn't work with `?`-desugaring. If the `nightly` feature is //! enabled for this crate, the `std` version is enabled. #[cfg(not(feature = "nightly"))] pub use stable::{FromResidual, Try}; #[cfg(feature = "nightly")] pub use std::ops::{FromResidual, Try}; mod stable { use std::{convert, ops::ControlFlow, task::Poll}; pub trait Try: FromResidual { type Output; type Residual; fn from_output(output: Self::Output) -> Self; fn branch(self) -> ControlFlow; } pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; } impl Try for ControlFlow { type Output = C; type Residual = ControlFlow; #[inline] fn from_output(output: Self::Output) -> Self { ControlFlow::Continue(output) } #[inline] fn branch(self) -> ControlFlow { match self { ControlFlow::Continue(c) => ControlFlow::Continue(c), ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), } } } impl FromResidual for ControlFlow { #[inline] fn from_residual(residual: ControlFlow) -> Self { match residual { ControlFlow::Break(b) => ControlFlow::Break(b), _ => unreachable!(), } } } impl Try for Option { type Output = T; type Residual = Option; #[inline] fn from_output(output: Self::Output) -> Self { Some(output) } #[inline] fn branch(self) -> ControlFlow { match self { Some(v) => ControlFlow::Continue(v), None => ControlFlow::Break(None), } } } impl FromResidual for Option { #[inline] fn from_residual(residual: Option) -> Self { match residual { None => None, _ => unreachable!(), } } } impl Try for Result { type Output = T; type Residual = Result; #[inline] fn from_output(output: Self::Output) -> Self { Ok(output) } #[inline] fn branch(self) -> ControlFlow { match self { Ok(v) => ControlFlow::Continue(v), Err(e) => ControlFlow::Break(Err(e)), } } } impl> FromResidual> for Result { #[inline] fn from_residual(residual: Result) -> Self { match residual { Err(e) => Err(From::from(e)), _ => unreachable!(), } } } impl Try for Poll>> { type Output = Poll>; type Residual = Result; #[inline] fn from_output(c: Self::Output) -> Self { c.map(|x| x.map(Ok)) } #[inline] fn branch(self) -> ControlFlow { match self { Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))), Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)), Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)), Poll::Pending => ControlFlow::Continue(Poll::Pending), } } } impl> FromResidual> for Poll>> { #[inline] fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Some(Err(From::from(e)))), _ => unreachable!(), } } } impl Try for Poll> { type Output = Poll; type Residual = Result; #[inline] fn from_output(c: Self::Output) -> Self { c.map(Ok) } #[inline] fn branch(self) -> ControlFlow { match self { Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)), Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)), Poll::Pending => ControlFlow::Continue(Poll::Pending), } } } impl> FromResidual> for Poll> { #[inline] fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Err(From::from(e))), _ => unreachable!(), } } } }