use std::{
borrow::{Borrow, Cow},
collections::{BTreeMap, HashMap},
hash::{BuildHasher, Hash},
ops::Deref,
rc::Rc,
sync::Arc,
};
pub trait Values {
fn get_value(&self, key: &str) -> Option<Cow<'_, str>>;
}
impl<T> Values for &T
where
T: Values,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
T::get_value(self, key)
}
}
impl<T> Values for Arc<T>
where
T: Values,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
T::get_value(self.deref(), key)
}
}
impl<T> Values for Rc<T>
where
T: Values,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
T::get_value(self.deref(), key)
}
}
impl<K, V> Values for [(K, V)]
where
K: AsRef<str>,
V: AsRef<str>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
self.iter().find_map(|(k, v)| {
if k.as_ref() == key {
Some(Cow::Borrowed(v.as_ref()))
} else {
None
}
})
}
}
impl<K, V> Values for &[(K, V)]
where
K: AsRef<str>,
V: AsRef<str>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
(*self).get_value(key)
}
}
impl<K, V, const N: usize> Values for [(K, V); N]
where
K: AsRef<str>,
V: AsRef<str>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
self.as_slice().get_value(key)
}
}
impl<K, V> Values for Vec<(K, V)>
where
K: AsRef<str>,
V: AsRef<str>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
self.as_slice().get_value(key)
}
}
impl<K, V, S> Values for HashMap<K, V, S>
where
K: Borrow<str> + Eq + Hash,
V: AsRef<str>,
S: BuildHasher,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
self.get(key).map(|v| Cow::Borrowed(v.as_ref()))
}
}
impl<K, V> Values for BTreeMap<K, V>
where
K: Borrow<str> + Ord,
V: AsRef<str>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
self.get(key).map(|v| Cow::Borrowed(v.as_ref()))
}
}
#[derive(Copy, Clone, Debug)]
pub struct ValuesFn<F> {
inner: F,
}
impl<F> Values for ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'static, str>>,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
(self.inner)(key)
}
}
impl<F> From<F> for ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'static, str>>,
{
fn from(inner: F) -> Self {
Self { inner }
}
}
pub const fn vals<F>(func: F) -> ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'static, str>>,
{
ValuesFn { inner: func }
}