use super::OptionElse;
use std::collections::HashMap;
use std::hash::Hash;
pub trait OptionExtensions<T>: Sized {
fn convert<U>(self, converter: impl FnOnce(T) -> U) -> Option<U>;
fn convert_optional<U>(self, converter: impl FnOnce(T) -> Option<U>) -> Option<U>;
fn convert_or<U>(self, converter: impl FnOnce(T) -> U, fallback_converter: impl FnOnce() -> U) -> U;
fn if_has_value(self, action: impl FnOnce(T)) -> OptionElse;
fn value_or(self, value_selector: impl FnOnce() -> T) -> T;
fn value_or_default(self) -> T
where
T: Default;
fn value_or_throw<E>(self, exception_generator: impl FnOnce() -> E) -> Result<T, E>;
}
impl<T> OptionExtensions<T> for Option<T> {
fn convert<U>(self, converter: impl FnOnce(T) -> U) -> Option<U> {
self.map(converter)
}
fn convert_optional<U>(self, converter: impl FnOnce(T) -> Option<U>) -> Option<U> {
self.and_then(converter)
}
fn convert_or<U>(self, converter: impl FnOnce(T) -> U, fallback_converter: impl FnOnce() -> U) -> U {
match self {
Some(value) => converter(value),
None => fallback_converter(),
}
}
fn if_has_value(self, action: impl FnOnce(T)) -> OptionElse {
match self {
Some(value) => {
action(value);
OptionElse::no_action()
}
None => OptionElse::run(),
}
}
fn value_or(self, value_selector: impl FnOnce() -> T) -> T {
self.unwrap_or_else(value_selector)
}
fn value_or_default(self) -> T
where
T: Default,
{
self.unwrap_or_default()
}
fn value_or_throw<E>(self, exception_generator: impl FnOnce() -> E) -> Result<T, E> {
self.ok_or_else(exception_generator)
}
}
pub fn first_or_optional<T>(source: impl IntoIterator<Item = T>, selector: impl Fn(&T) -> bool) -> Option<T> {
source.into_iter().find(|item| selector(item))
}
pub fn lookup<K: Eq + Hash, V: Clone>(source: &HashMap<K, V>, key: &K) -> Option<V> {
source.get(key).cloned()
}
pub fn remove_if_contained<K: Eq + Hash, V>(source: &mut HashMap<K, V>, key: &K) -> bool {
source.remove(key).is_some()
}
pub fn select_values<T>(source: impl IntoIterator<Item = Option<T>>) -> Vec<T> {
source.into_iter().flatten().collect()
}