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>
This commit is contained in:
Jiahao XU 2023-03-26 16:11:10 +11:00 committed by GitHub
parent 47d4aeaa96
commit a27d5aebf6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 512 additions and 312 deletions

View file

@ -1,4 +1,35 @@
/// Construct a template constant without needing to make an items constant.
#[doc(hidden)]
#[macro_export]
macro_rules! __template_item {
() => {};
({ $key:literal }) => {
$crate::Item::Key($key)
};
( $text:literal ) => {
$crate::Item::Text($text)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __template_impl {
($( $token:tt ),* ; $default:expr) => {
$crate::Template::new(
{
const ITEMS: &'static [$crate::Item<'static>] = &[
$(
$crate::__template_item!($token)
),*
];
ITEMS
},
$default,
)
};
}
/// Construct a template constant using syntax similar to the template to be
/// passed to [`Template::parse`].
///
/// This is essentially a shorthand for:
///
@ -13,9 +44,8 @@
/// # Examples
///
/// ```
/// use leon::Item::*;
/// assert_eq!(
/// leon::template!(Text("Hello "), Key("name"))
/// leon::template!("Hello ", {"name"})
/// .render(&[("name", "Магда Нахман")])
/// .unwrap(),
/// "Hello Магда Нахман",
@ -25,9 +55,8 @@
/// With a default:
///
/// ```
/// use leon::Item::*;
/// assert_eq!(
/// leon::template!(Text("Hello "), Key("name"); "M. P. T. Acharya")
/// leon::template!("Hello ", {"name"}; "M. P. T. Acharya")
/// .render(&[("city", "Madras")])
/// .unwrap(),
/// "Hello M. P. T. Acharya",
@ -35,16 +64,93 @@
/// ```
#[macro_export]
macro_rules! template {
($($item:expr),* $(,)?) => {
$crate::Template::new({
const ITEMS: &'static [$crate::Item<'static>] = &[$($item),*];
ITEMS
}, ::core::option::Option::None)
() => {
$crate::Template::new(
{
const ITEMS: &'static [$crate::Item<'static>] = &[];
ITEMS
},
::core::option::Option::None,
)
};
($($item:expr),* $(,)? ; $default:expr) => {
$crate::Template::new({
const ITEMS: &'static [$crate::Item<'static>] = &[$($item),*];
ITEMS
}, ::core::option::Option::Some($default))
($( $token:tt ),* $(,)?) => {
$crate::__template_impl!($( $token ),* ; ::core::option::Option::None)
};
($( $token:tt ),* $(,)? ; $default:expr) => {
$crate::__template_impl!($( $token ),* ; ::core::option::Option::Some($default))
};
}
#[cfg(test)]
mod tests {
use crate::{template, Item, Template};
#[test]
fn test_template2() {
assert_eq!(template!(), Template::new(&[], None),);
// Only literals
assert_eq!(template!("1"), Template::new(&[Item::Text("1")], None));
assert_eq!(
template!("1", "2"),
Template::new(&[Item::Text("1"), Item::Text("2")], None)
);
assert_eq!(
template!("1", "2", "3"),
Template::new(&[Item::Text("1"), Item::Text("2"), Item::Text("3")], None)
);
// Only keys
assert_eq!(template!({ "k1" }), Template::new(&[Item::Key("k1")], None));
assert_eq!(
template!({ "k1" }, { "k2" }),
Template::new(&[Item::Key("k1"), Item::Key("k2")], None)
);
assert_eq!(
template!({ "k1" }, { "k2" }, { "k3" }),
Template::new(&[Item::Key("k1"), Item::Key("k2"), Item::Key("k3")], None)
);
// Mixed
assert_eq!(
template!("1", { "k1" }, "3"),
Template::new(&[Item::Text("1"), Item::Key("k1"), Item::Text("3")], None)
);
assert_eq!(
template!("1", "2", { "k1" }, "3", "4"),
Template::new(
&[
Item::Text("1"),
Item::Text("2"),
Item::Key("k1"),
Item::Text("3"),
Item::Text("4")
],
None
)
);
assert_eq!(
template!("1", "2", { "k1" }, { "k2" }, "3", "4", { "k3" }),
Template::new(
&[
Item::Text("1"),
Item::Text("2"),
Item::Key("k1"),
Item::Key("k2"),
Item::Text("3"),
Item::Text("4"),
Item::Key("k3"),
],
None
)
);
}
}