snm_core/
fetcher.rs

1use console::style;
2use serde::Deserialize;
3use url::Url;
4
5use super::{
6    version::{DistVersion, UserVersion},
7    SnmRes,
8};
9
10#[derive(Debug, PartialEq, Eq)]
11pub enum Lts {
12    No,
13    Yes(String),
14}
15
16// NOTE:
17// I had to manually implement deserializer because the lts codename is coming from api
18// is in sentence case. So I am converting it to lowercase to be consistent.
19impl<'de> Deserialize<'de> for Lts {
20    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21    where
22        D: serde::Deserializer<'de>,
23    {
24        let val = match String::deserialize(deserializer) {
25            Ok(v) => Self::Yes(v.to_lowercase()),
26            _ => Self::No,
27        };
28
29        Ok(val)
30    }
31}
32
33#[derive(Debug, Deserialize)]
34pub struct Release {
35    pub version: DistVersion,
36    pub lts: Lts,
37}
38
39pub struct Fetcher {
40    releases: Vec<Release>,
41}
42
43impl Fetcher {
44    pub fn fetch(mirror: &Url) -> SnmRes<Self> {
45        let releases: Vec<Release> = ureq::get(&format!("{}/index.json", mirror))
46            .call()?
47            .into_json()?;
48
49        Ok(Self { releases })
50    }
51
52    pub fn lts(&self) -> SnmRes<&Release> {
53        self.releases
54            .iter()
55            .find(|x| matches!(x.lts, Lts::Yes(_)))
56            .ok_or_else(|| anyhow::anyhow!("Unable to find {} release", style("lts").bold()))
57    }
58
59    pub fn latest(&self) -> SnmRes<&Release> {
60        self.releases
61            .iter()
62            .find(|x| matches!(x.lts, Lts::No))
63            .ok_or_else(|| anyhow::anyhow!("Unable to find {} release", style("latest").bold()))
64    }
65
66    pub fn find_release(&self, version: &UserVersion) -> Option<&Release> {
67        self.releases
68            .iter()
69            .find(|release| version.match_release(release))
70    }
71
72    pub fn find_releases(self, version: &UserVersion) -> Vec<Release> {
73        self.releases
74            .into_iter()
75            .filter(|v| version.match_release(v))
76            .collect()
77    }
78
79    pub fn get_all(self) -> Vec<Release> {
80        self.releases
81    }
82}