mirror of
https://seed.radicle.dev/rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt.git
synced 2026-11-10 21:50:39 +08:00
radicle-git init
Port over all git relevant parts of the radicle-link repository[0]. The packages that are kept are: * git-ext * git-ref-format * git-trailers * link-git * macros * std-ext * test -- only the portions that test the above The development and testing scripts are also added for local and CI testing. [0]: https://github.com/radicle-dev/radicle-link/ Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "radicle-std-ext"
|
||||
version = "0.1.0"
|
||||
authors = ["The Radicle Team <dev@radicle.xyz>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later"
|
||||
description = "Monkey patches of std types"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
test = false
|
||||
|
||||
[features]
|
||||
default = []
|
||||
nightly = []
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright © 2019-2020 The Radicle Foundation <hello@radicle.foundation>
|
||||
//
|
||||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
|
||||
// Linking Exception. For full terms see the included LICENSE file.
|
||||
|
||||
#![cfg_attr(feature = "nightly", feature(try_trait_v2))]
|
||||
|
||||
pub mod ops;
|
||||
pub mod result;
|
||||
|
||||
pub type Void = std::convert::Infallible;
|
||||
|
||||
pub mod prelude {
|
||||
use super::*;
|
||||
|
||||
pub use super::Void;
|
||||
pub use ops::{FromResidual, Try};
|
||||
pub use result::ResultExt;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// 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<Self::Residual, Self::Output>;
|
||||
}
|
||||
|
||||
pub trait FromResidual<R = <Self as Try>::Residual> {
|
||||
fn from_residual(residual: R) -> Self;
|
||||
}
|
||||
|
||||
impl<B, C> Try for ControlFlow<B, C> {
|
||||
type Output = C;
|
||||
type Residual = ControlFlow<B, convert::Infallible>;
|
||||
|
||||
#[inline]
|
||||
fn from_output(output: Self::Output) -> Self {
|
||||
ControlFlow::Continue(output)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
ControlFlow::Continue(c) => ControlFlow::Continue(c),
|
||||
ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, C> FromResidual for ControlFlow<B, C> {
|
||||
#[inline]
|
||||
fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
|
||||
match residual {
|
||||
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Try for Option<T> {
|
||||
type Output = T;
|
||||
type Residual = Option<convert::Infallible>;
|
||||
|
||||
#[inline]
|
||||
fn from_output(output: Self::Output) -> Self {
|
||||
Some(output)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
Some(v) => ControlFlow::Continue(v),
|
||||
None => ControlFlow::Break(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromResidual for Option<T> {
|
||||
#[inline]
|
||||
fn from_residual(residual: Option<convert::Infallible>) -> Self {
|
||||
match residual {
|
||||
None => None,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Try for Result<T, E> {
|
||||
type Output = T;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
#[inline]
|
||||
fn from_output(output: Self::Output) -> Self {
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
Ok(v) => ControlFlow::Continue(v),
|
||||
Err(e) => ControlFlow::Break(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Result<T, F> {
|
||||
#[inline]
|
||||
fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
|
||||
match residual {
|
||||
Err(e) => Err(From::from(e)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Try for Poll<Option<Result<T, E>>> {
|
||||
type Output = Poll<Option<T>>;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
#[inline]
|
||||
fn from_output(c: Self::Output) -> Self {
|
||||
c.map(|x| x.map(Ok))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
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<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Option<Result<T, F>>> {
|
||||
#[inline]
|
||||
fn from_residual(x: Result<convert::Infallible, E>) -> Self {
|
||||
match x {
|
||||
Err(e) => Poll::Ready(Some(Err(From::from(e)))),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Try for Poll<Result<T, E>> {
|
||||
type Output = Poll<T>;
|
||||
type Residual = Result<convert::Infallible, E>;
|
||||
|
||||
#[inline]
|
||||
fn from_output(c: Self::Output) -> Self {
|
||||
c.map(Ok)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
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<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
|
||||
#[inline]
|
||||
fn from_residual(x: Result<convert::Infallible, E>) -> Self {
|
||||
match x {
|
||||
Err(e) => Poll::Ready(Err(From::from(e))),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright © 2019-2020 The Radicle Foundation <hello@radicle.foundation>
|
||||
//
|
||||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
|
||||
// Linking Exception. For full terms see the included LICENSE file.
|
||||
|
||||
pub trait ResultExt<T, E> {
|
||||
/// Calls `f` if the result is [`Err`], **and** the predicate `pred` on the
|
||||
/// error value returns true. Otherwise returns the [`Ok`] value of
|
||||
/// `self`. Note that `f` may change the error type, so as long as the
|
||||
/// target type can be converted from the original one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io;
|
||||
/// use radicle_std_ext::result::ResultExt as _;
|
||||
///
|
||||
/// let res = Err(io::Error::new(io::ErrorKind::Other, "crashbug"))
|
||||
/// .or_matches::<io::Error, _, _>(|e| matches!(e.kind(), io::ErrorKind::Other), || Ok(()))
|
||||
/// .unwrap();
|
||||
///
|
||||
/// assert_eq!((), res)
|
||||
/// ```
|
||||
fn or_matches<E2, P, F>(self, pred: P, f: F) -> Result<T, E2>
|
||||
where
|
||||
E2: From<E>,
|
||||
P: FnOnce(&E) -> bool,
|
||||
F: FnOnce() -> Result<T, E2>;
|
||||
}
|
||||
|
||||
impl<T, E> ResultExt<T, E> for Result<T, E> {
|
||||
fn or_matches<E2, P, F>(self, pred: P, f: F) -> Result<T, E2>
|
||||
where
|
||||
E2: From<E>,
|
||||
P: FnOnce(&E) -> bool,
|
||||
F: FnOnce() -> Result<T, E2>,
|
||||
{
|
||||
self.or_else(|e| if pred(&e) { f() } else { Err(e.into()) })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user