use crate::{models::*, Client, IntoPackageIdent, IntoVersionIdent, Result};
use async_stream::try_stream;
use futures_core::Stream;
use std::fmt::Display;
impl Client {
pub async fn get_metrics(
&self,
community: impl AsRef<str>,
package: impl IntoPackageIdent<'_>,
) -> Result<PackageMetrics> {
let url = self.v1_url(
community,
format_args!("/package-metrics/{}", package.into_id()?.path()),
);
self.get_json(url).await
}
pub async fn get_downloads(
&self,
community: impl AsRef<str>,
version: impl IntoVersionIdent<'_>,
) -> Result<u64> {
let url = self.v1_url(
community,
format_args!("/package-metrics/{}", version.into_id()?.path()),
);
let response: PackageVersionMetrics = self.get_json(url).await?;
Ok(response.downloads)
}
pub async fn list_packages_v1(&self, community: impl AsRef<str>) -> Result<Vec<PackageV1>> {
let url = self.v1_url(community, "/package");
self.get_json(url).await
}
fn v1_url(&self, community: impl AsRef<str>, path: impl Display) -> String {
format!("{}/c/{}/api/v1{}", self.base_url, community.as_ref(), path)
}
}
impl Client {
pub async fn stream_packages_v1(
&self,
community: impl AsRef<str>,
) -> Result<impl Stream<Item = Result<PackageV1>>> {
let url = self.v1_url(community.as_ref(), "/package");
let mut response = self.get(url).await?;
Ok(try_stream! {
let mut buffer = Vec::new();
let mut string = String::new();
let mut is_first = true;
while let Some(chunk) = response.chunk().await? {
buffer.extend_from_slice(&chunk);
let chunk = match std::str::from_utf8(&buffer) {
Ok(chunk) => chunk,
Err(_) => continue,
};
if is_first {
is_first = false;
string.extend(chunk.chars().skip(1)); } else {
string.push_str(chunk);
}
buffer.clear();
while let Some(index) = string.find("}]},") {
let (json, _) = string.split_at(index + 3);
yield serde_json::from_str::<PackageV1>(json)?;
string.replace_range(..index + 4, "");
}
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures_util::{pin_mut, TryStreamExt};
#[tokio::test]
async fn stream_packages_v1() -> Result<()> {
let client = Client::new();
let stream = client.stream_packages_v1("muck").await?;
pin_mut!(stream);
let mut count = 0;
while let Some(_) = stream.try_next().await? {
count += 1;
}
assert!(count > 0);
Ok(())
}
}