cargo-binstall/crates/leon/src/values.rs
Jiahao XU a27d5aebf6
Use leon for template in binstalk & detect malformed pkg-url/pkg-fmt early (#933)
Fixed #851

* Add new dep leon to crate binstalk
* Add new variant `BinstallError::Template{Parse, Render}Error`
* Use `leon::Template` in mod `bins`
* Use `leon::Template` in mod `fetchers::gh_crate_meta`
* Refactor mod `bins`: Rm unused associated fn & fields from `Context`
* Simplify unit testing in mod `fetchers::gh_crate_meta`
* Rm soft-deprecated field `fetchers::gh_crate_meta::Context::format`
  and change the `match` to resolve `archive` => `self.archive_format`.
* Make macro_rules `leon::template!` far easier to use
* Construct `leon::Template<'_>` as constant in `gh_crate_meta::hosting`
* Simplify `leon::Values` trait
   Change its method `get_value` signature to
   
   ```rust
       fn get_value(&self, key: &str) -> Option<Cow<'_, str>>;
   ```
   
   Now, `ValuesFn` also accepts non-`'static` function, but now
   `leon::Values` is only implemented for `&ValuesFn<F>` now.
   
   This makes it a little bit more cumbersome to use but I think it's a
   reasonable drawback.
* Rm `Send` bound req from `ValuesFn`
* Impl new fn `leon::Template::cast`
   for casting `Template<'s>` to `Template<'t>` where `'s: 't`
* Rename `leon::Template::has_keys` => `has_any_of_keys`
* Make checking whether format related keys are present more robust
* Optimize `GhCrateMeta::launch_baseline_find_tasks`: Skip checking all fmt ext
   if none of the format related keys ("format", "archive-format",
   "archive-suffix") are present.
* Only ret `.exe` in `PkgFmt::extensions` on windows
   by adding a new param `is_windows: bool`
* Improve debug msg in `GhCrateMeta::fetch_and_extract`
* Add warnings to `GhCrateMeta::find`
* Rm dep tinytemplate
* `impl<'s, 'rhs: 's> ops::AddAssign<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::AddAssign<Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<&Item<'item>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::Add<Template<'rhs>> for Template<'s>` (improved existing `Add` impl)
* `impl<'s, 'rhs: 's> ops::Add<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<&Item<'item>> for Template<'s>`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
Co-authored-by: Félix Saparelli <felix@passcod.name>
2023-03-26 16:11:10 +11:00

130 lines
2.6 KiB
Rust

use std::{
borrow::{Borrow, Cow},
collections::{BTreeMap, HashMap},
hash::{BuildHasher, Hash},
};
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<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()))
}
}
/// Workaround to allow using functions as [`Values`].
///
/// As this isn't constructible you'll want to use [`vals()`] instead.
pub struct ValuesFn<F> {
inner: F,
}
impl<'s, F> Values for &'s ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'s, str>> + 's,
{
fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
(self.inner)(key)
}
}
impl<'f, F> From<F> for ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'f, str>> + 'f,
{
fn from(inner: F) -> Self {
Self { inner }
}
}
/// Workaround to allow using functions as [`Values`].
///
/// Wraps your function so it implements [`Values`].
///
/// # Example
///
/// ```
/// use leon::{Values, vals};
///
/// fn use_values(_values: impl Values) {}
///
/// use_values(&vals(|_| Some("hello".into())));
/// ```
pub const fn vals<'f, F>(func: F) -> ValuesFn<F>
where
F: Fn(&str) -> Option<Cow<'f, str>> + 'f,
{
ValuesFn { inner: func }
}