pub fn map_some_or<T, U, F>(opt: Option<T>, default: U, f: F) -> U
where
F: FnOnce(T) -> U,
{
match opt {
Some(v) => f(v),
None => default,
}
}
pub fn map_ok_or<T, E, U, F>(res: Result<T, E>, default: U, f: F) -> U
where
F: FnOnce(T) -> U,
{
match res {
Ok(v) => f(v),
Err(_) => default,
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NonEmptyVec<T> {
head: T,
tail: Vec<T>,
}
impl<T> NonEmptyVec<T> {
pub fn new(head: T, tail: Vec<T>) -> Self {
Self { head, tail }
}
pub fn from_vec(mut v: Vec<T>) -> Option<Self> {
if v.is_empty() {
None
} else {
let head = v.remove(0);
Some(Self { head, tail: v })
}
}
pub fn len(&self) -> usize {
1 + self.tail.len()
}
pub fn is_empty(&self) -> bool {
false
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
std::iter::once(&self.head).chain(self.tail.iter())
}
}
pub fn try_cast<T: 'static, U: 'static + Clone>(t: &T) -> Result<U, &'static str> {
use core::any::Any;
let any_ref = t as &dyn Any;
if let Some(u_ref) = any_ref.downcast_ref::<U>() {
Ok(u_ref.clone())
} else {
Err("downcast failed")
}
}
pub fn coerce(x: i64, min: i64, max: i64) -> i64 {
if x < min {
min
} else if x > max {
max
} else {
x
}
}
pub fn is_some_and<T, F: FnOnce(&T) -> bool>(opt: Option<T>, f: F) -> bool {
opt.as_ref().is_some_and(f)
}
pub fn is_ok_and<T, E, F: FnOnce(&T) -> bool>(res: Result<T, E>, f: F) -> bool {
res.as_ref().is_ok_and(f)
}
pub fn as_ref_or<'a, T>(opt: Option<&'a T>, default: &'a T) -> &'a T {
opt.unwrap_or(default)
}
pub fn take_if<T, F: FnOnce(&T) -> bool>(opt: &mut Option<T>, f: F) -> Option<T> {
if opt.as_ref().is_some_and(f) {
opt.take()
} else {
None
}
}
pub fn replace_with<T>(slot: &mut T, new_val: T) -> T {
std::mem::replace(slot, new_val)
}
pub fn type_name_short<T>() -> &'static str {
std::any::type_name::<T>().rsplit("::").next().unwrap_or("")
}