#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::restriction)]
#![warn(clippy::nursery)]
#![warn(clippy::cargo)]
#![allow(clippy::blanket_clippy_restriction_lints)]
#![allow(clippy::implicit_return)]
#![allow(clippy::panic)]
#![allow(clippy::expect_used)]
#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::integer_arithmetic)]
#![allow(clippy::pub_use)]
#![cfg_attr(not(feature = "std"), no_std)]
use core::{fmt::Debug, option::Option, result::Result};
include!(concat!(env!("OUT_DIR"), "/assets.rs"));
pub trait ExpectoPatronumExt: sealed::Sealed {
type Success;
fn expecto_patronum(self, msg: &str) -> Self::Success;
}
impl<T, E: Debug> ExpectoPatronumExt for Result<T, E> {
type Success = T;
#[inline]
fn expecto_patronum(self, msg: &str) -> Self::Success {
self.unwrap_or_else(|error| {
let patronus = choose_patronus(msg);
let panic_msg = construct_panic_msg(patronus, msg);
panic!("{panic_msg}: {error:?}")
})
}
}
impl<T> ExpectoPatronumExt for Option<T> {
type Success = T;
#[inline]
fn expecto_patronum(self, msg: &str) -> Self::Success {
self.unwrap_or_else(|| {
let patronus = choose_patronus(msg);
let panic_msg = construct_panic_msg(patronus, msg);
panic!("{panic_msg}")
})
}
}
mod sealed {
pub trait Sealed {}
impl<T, E: super::Debug> Sealed for super::Result<T, E> {}
impl<T> Sealed for super::Option<T> {}
}
type Patronus = &'static str;
#[allow(clippy::indexing_slicing)]
fn choose_patronus(msg: &str) -> Patronus {
let n: u128 = fastmurmur3::hash(msg.as_bytes())
% u128::try_from(ASSETS.len()).expect("`usize` should fit in `u128`");
ASSETS[usize::try_from(n).expect("Calculated index should fit in `usize`")]
}
fn construct_panic_msg(patronus: Patronus, base_msg: &str) -> String {
let mut new_msg = String::with_capacity(patronus.len() + base_msg.len() + 1);
new_msg.push('\n');
new_msg.push_str(patronus);
new_msg.push_str(base_msg);
new_msg
}
pub mod prelude {
pub use super::ExpectoPatronumExt as _;
}