#![doc = include_str!("../README.md")]
#![no_std]
#[rustfmt::skip]
pub mod prelude {
pub use crate::{Permit as _};
}
pub trait Permit<E> {
fn permit<F>(self, f: F) -> Result<(), E>
where
F: FnOnce(&E) -> bool;
fn permit_if(self, condition: bool) -> Result<(), E>;
}
impl<E> Permit<E> for Result<(), E> {
fn permit<F>(self, f: F) -> Result<(), E>
where
F: FnOnce(&E) -> bool,
{
match self {
Ok(()) => Ok(()), Err(ref e) if f(e) => Ok(()), Err(e) => Err(e), }
}
fn permit_if(self, condition: bool) -> Result<(), E> {
match self {
Ok(()) => Ok(()), Err(_) if condition => Ok(()), Err(e) => Err(e), }
}
}
#[cfg(test)]
mod tests {
extern crate std;
use super::*;
use anyhow::bail;
use std::io::{ErrorKind, Write};
use std::string::ToString;
use std::{fs, io};
fn ls(path: &str) -> anyhow::Result<()> {
if let Err(e) = fs::read_dir(path) {
bail!(e)
};
Ok(())
}
#[test]
fn permit_an_error_and_succeed() {
assert!(
io::stdout()
.flush()
.permit(|e| e.kind() == ErrorKind::FileTooLarge)
.is_ok()
)
}
#[test]
fn permit_an_error_and_fail() {
assert!(
fs::create_dir("/path/to/nonexistent/directory")
.permit(|e| e.kind() == io::ErrorKind::PermissionDenied)
.is_err()
)
}
#[test]
fn anyhow_always_permit() {
assert!(ls("/etc/sudoers.d").permit_if(true).is_ok())
}
#[test]
fn anyhow_never_permit() {
assert!(ls("/etc/sudoers.d").permit_if(false).is_err())
}
#[test]
fn anyhow_succeed_after_permitting() {
assert!(
ls("/root")
.permit(|e| e.to_string().contains("Permission"))
.is_ok()
)
}
#[test]
fn anyhow_fail_after_permitting() {
assert!(
ls("/etc/sudoers.d")
.permit(|e| e.to_string().contains("stuff it doesn't contain"))
.is_err()
)
}
#[test]
fn anyhow_succeed() {
assert!(
ls(".")
.permit(|e| e.to_string().contains("there shouldn't be an error"))
.is_ok()
)
}
#[test]
fn chain_and_succeed() {
assert!(
fs::create_dir("/test")
.permit(|e| e.kind() == io::ErrorKind::AlreadyExists)
.permit(|e| e.kind() == io::ErrorKind::PermissionDenied)
.is_ok()
)
}
}