use crate::{Result, Versions};
pub use max::*;
pub use newest::*;
use semver::Version;
pub fn get_versions(crate_name: &str, user_agent: &str) -> Result<Versions> {
let url = format!(
"https://crates.io/api/v1/crates/{crate_name}",
crate_name = crate_name,
);
let response: serde_json::Value = reqwest::blocking::Client::builder()
.user_agent(format!("{}/{}", crate_name, user_agent))
.build()
.map_err(|_| "Couldn't build client")?
.get(&url)
.send()
.map_err(|_| "Couldn't request crate info")?
.json()
.map_err(|_| "Couldn't parse response to JSON")?;
let crate_data = response.get("crate").ok_or("Unexpected JSON format")?;
let max_version = crate_data
.get("max_version")
.ok_or("Unexpected JSON format")?
.as_str()
.ok_or("Couldn't parse max version as str")?;
let newest_version = crate_data
.get("newest_version")
.ok_or("Unexpected JSON format")?
.as_str()
.ok_or("Couldn't parse newest version as str")?;
let max_version = Version::parse(max_version).map_err(|_| "Couldn't parse max version")?;
let newest_version = Version::parse(newest_version)
.map_err(|_| "Couldn't parse newest version")?;
let versions = Versions {
max_version,
newest_version,
};
Ok(versions)
}
fn get_version_list(crate_name: &str, user_agent: &str) -> Result<Vec<Version>> {
let url = format!(
"https://crates.io/api/v1/crates/{crate_name}",
crate_name = crate_name,
);
let response: serde_json::Value = reqwest::blocking::Client::builder()
.user_agent(format!("{}/{}", crate_name, user_agent))
.build()
.map_err(|_| "Couldn't build client")?
.get(&url)
.send()
.map_err(|_| "Couldn't request crate info")?
.json()
.map_err(|_| "Couldn't parse response to JSON")?;
let versions = response
.get("versions")
.ok_or("Version list not found")?
.as_array()
.ok_or("Couldn't parse version list as array")?;
let versions = versions
.iter()
.filter_map(|v| v.get("num"))
.filter_map(|v| v.as_str())
.map(|v| Version::parse(v))
.filter_map(|v| v.ok())
.collect();
Ok(versions)
}
#[macro_export]
macro_rules! versions {
() => {
$crate::versions!(
crate_name = $crate::crate_name!(),
user_agent = $crate::user_agent!(),
)
};
(crate_name = $crate_name:expr, user_agent = $user_agent:expr $(,)?) => {
$crate::blocking::get_versions($crate_name, $user_agent)
};
(user_agent = $user_agent:expr, crate_name = $crate_name:expr $(,)?) => {
$crate::versions!(crate_name = $crate_name, user_agent = $user_agent)
};
(crate_name = $crate_name:expr $(,)?) => {
$crate::versions!(
crate_name = $crate_name,
user_agent = $crate::user_agent!(),
)
};
(user_agent = $user_agent:expr $(,)?) => {
$crate::versions!(
crate_name = $crate::crate_name!(),
user_agent = $user_agent,
)
};
}
mod max;
mod newest;