1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#[cfg(feature = "colors")]
use colored::Colorize;
use std::{fmt, fmt::Formatter, time::Duration};
const TIMEOUT: u64 = 5;
pub enum Availability {
Available,
Unavailable,
Unknown,
}
impl fmt::Display for Availability {
#[cfg(not(feature = "colors"))]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Availability::Available => write!(f, "{}", "Available"),
Availability::Unavailable => write!(f, "{}", "Unavailable"),
Availability::Unknown => write!(f, "{}", "Unknown"),
}
}
#[cfg(feature = "colors")]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Availability::Available => write!(f, "{}", "Available".green()),
Availability::Unavailable => write!(f, "{}", "Unavailable".red()),
Availability::Unknown => write!(f, "{}", "Unknown".bright_black()),
}
}
}
pub fn check_availability(name: impl AsRef<str>) -> Result<Availability, ()> {
let name = name.as_ref();
if name.is_empty() {
eprintln!("Crate name can't be empty");
return Err(());
}
let url = format!("https://crates.io/api/v1/crates/{}", name);
let resp = ureq::get(&url).timeout(Duration::from_secs(TIMEOUT)).call();
let availability = match resp.status() {
200 => Availability::Unavailable,
404 => Availability::Available,
_ => Availability::Unknown,
};
Ok(availability)
}