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>; } impl Values for &T where T: Values, { fn get_value(&self, key: &str) -> Option> { T::get_value(self, key) } } impl Values for Arc where T: Values, { fn get_value(&self, key: &str) -> Option> { T::get_value(self.deref(), key) } } impl Values for Rc where T: Values, { fn get_value(&self, key: &str) -> Option> { T::get_value(self.deref(), key) } } impl Values for [(K, V)] where K: AsRef, V: AsRef, { fn get_value(&self, key: &str) -> Option> { self.iter().find_map(|(k, v)| { if k.as_ref() == key { Some(Cow::Borrowed(v.as_ref())) } else { None } }) } } impl Values for &[(K, V)] where K: AsRef, V: AsRef, { fn get_value(&self, key: &str) -> Option> { (*self).get_value(key) } } impl Values for [(K, V); N] where K: AsRef, V: AsRef, { fn get_value(&self, key: &str) -> Option> { self.as_slice().get_value(key) } } impl Values for Vec<(K, V)> where K: AsRef, V: AsRef, { fn get_value(&self, key: &str) -> Option> { self.as_slice().get_value(key) } } impl Values for HashMap where K: Borrow + Eq + Hash, V: AsRef, S: BuildHasher, { fn get_value(&self, key: &str) -> Option> { self.get(key).map(|v| Cow::Borrowed(v.as_ref())) } } impl Values for BTreeMap where K: Borrow + Ord, V: AsRef, { fn get_value(&self, key: &str) -> Option> { self.get(key).map(|v| Cow::Borrowed(v.as_ref())) } } /// Workaround to allow using functions as [`Values`]. /// /// As this isn't constructible you'll want to use [`vals()`] instead. #[derive(Copy, Clone, Debug)] pub struct ValuesFn { inner: F, } impl Values for ValuesFn where F: Fn(&str) -> Option>, { fn get_value(&self, key: &str) -> Option> { (self.inner)(key) } } /// See doc of [`vals`] impl From for ValuesFn where F: Fn(&str) -> Option>, { fn from(inner: F) -> Self { Self { inner } } } /// Wraps your function so it implements [`Values`], /// though it only works if your function returns `Cow<'static, str>`. /// /// Since regular function pointers cannot return anything other than /// `Cow<'static, str>` and closure in Rust currently does not support /// returning borrows of captured data, supporting anything other than /// `Cow<'static, str>` for functions is pointless and would only cause /// more confusion and compile-time errors. /// /// To return `&str` owned by the values itself, please create a newtype /// and implement [`Values`] on it manually instead of using this function. /// /// # Example /// /// ``` /// use leon::{Values, vals}; /// /// fn use_values(_values: impl Values) {} /// /// use_values(&vals(|_| Some("hello".into()))); /// ``` pub const fn vals(func: F) -> ValuesFn where F: Fn(&str) -> Option>, { ValuesFn { inner: func } }