1#![forbid(unsafe_code)]
8
9#[derive(Debug, Clone, PartialEq)]
11pub struct ArtifactDesc {
12 pub url: String,
13 pub archive: String,
15 pub sha256: String,
16 pub bin: Vec<String>,
18 pub strip: u32,
20}
21
22pub trait ToolProvider {
24 fn list_versions(&self) -> Vec<String>;
26 fn resolve(&self, version: &str, os: &str, arch: &str) -> Option<ArtifactDesc>;
28}
29
30pub fn render_url(template: &str, version: &str, os: &str, arch: &str, ext: &str) -> String {
33 template
34 .replace("{version}", version)
35 .replace("{os}", os)
36 .replace("{arch}", arch)
37 .replace("{ext}", ext)
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 struct Demo;
45 impl ToolProvider for Demo {
46 fn list_versions(&self) -> Vec<String> {
47 vec!["1.0.0".into(), "1.1.0".into()]
48 }
49 fn resolve(&self, version: &str, os: &str, arch: &str) -> Option<ArtifactDesc> {
50 Some(ArtifactDesc {
51 url: render_url(
52 "https://x.test/demo-{version}-{os}-{arch}.{ext}",
53 version,
54 os,
55 arch,
56 "tar.gz",
57 ),
58 archive: "tar.gz".into(),
59 sha256: "abc".into(),
60 bin: vec!["bin/demo".into()],
61 strip: 1,
62 })
63 }
64 }
65
66 #[test]
67 fn render_substitutes_all_placeholders() {
68 assert_eq!(
69 render_url(
70 "a/{version}/{os}-{arch}.{ext}",
71 "1.2.3",
72 "macos",
73 "arm64",
74 "tar.gz"
75 ),
76 "a/1.2.3/macos-arm64.tar.gz"
77 );
78 }
79
80 #[test]
81 fn author_trait_roundtrip() {
82 let p = Demo;
83 assert_eq!(p.list_versions().len(), 2);
84 let a = p.resolve("1.1.0", "linux", "x64").unwrap();
85 assert_eq!(a.url, "https://x.test/demo-1.1.0-linux-x64.tar.gz");
86 assert_eq!(a.strip, 1);
87 }
88}