nuget_client/ops/
get_package_versions.rs

1use std::pin::Pin;
2
3use futures::{Stream, StreamExt};
4use serde::{Deserialize, Serialize};
5use crate::Result;
6
7use crate::model::PackageMetadata;
8
9#[derive(Debug, Deserialize, Clone, Serialize)]
10struct RootResponse {
11    count: usize,
12    items: Vec<RegistrationPage>
13}
14
15#[derive(Debug, Deserialize, Clone, Serialize)]
16struct RegistrationPage {
17    #[serde(rename = "@id")]
18    id: String,
19    count: usize,
20    items: Option<Vec<RegistrationLeaf>>,
21    parent: Option<String>,
22    lower: Option<String>,
23    upper: Option<String>,
24}
25impl RegistrationPage {
26    async fn content<'a>(self, nuget: &'a crate::NugetRegistry) -> Result<OpaqueRegLeafStream<'a>> {
27        if let Some(items) = self.items {
28            return Ok(Box::pin(futures::stream::iter(items.into_iter().map(Ok))));
29        }
30
31        let url = nuget.client.get(self.id.clone()).send().await?.error_for_status()?.bytes().await?;
32        let url: RegistrationPage = serde_json::from_slice(&url)?;
33
34        Ok(Box::pin(futures::stream::iter(url.items.unwrap().into_iter().map(Ok))))
35    }
36}
37
38#[derive(Debug, Deserialize, Clone, Serialize)]
39#[non_exhaustive]
40#[serde(rename_all = "camelCase")]
41pub struct RegistrationLeaf {
42    #[serde(rename = "@id")]
43    pub id: String,
44    pub catalog_entry: PackageMetadata,
45    pub package_content: String,
46}
47
48type OpaqueRegLeafStream<'a> = Pin<Box<dyn Stream<Item=Result<RegistrationLeaf>> + Send + 'a>>;
49
50pub async fn execute<'a>(nuget: &'a crate::NugetRegistry, package_name: &str) -> Result<impl Stream<Item=Result<RegistrationLeaf>> + Send + Unpin + 'a> {
51    let base_url = nuget.resource_arr(&[
52        "RegistrationsBaseUrl/3.6.0",
53        "RegistrationsBaseUrl/3.4.0",
54        "RegistrationsBaseUrl/3.0.0-rc",
55        "RegistrationsBaseUrl/3.0.0-beta",
56        "RegistrationsBaseUrl/3.0.0",
57    ])?;
58
59    let mut suffix = format!("{}/index.json", package_name);
60    suffix.make_ascii_lowercase();
61    let url = base_url.join(&suffix)?;
62    dbg!((&base_url, &suffix, &url));
63
64    let root = nuget.client.get(url).send().await?.error_for_status()?.bytes().await?;
65    let root: RootResponse = serde_json::from_slice(&root)?;
66
67    dbg!(&root);
68
69    let mut stream = futures::stream::iter(root.items);
70    let mut stream = stream.flat_map(move |page| futures::stream::once(async move {
71        match page.content(nuget).await {
72            Ok(stream) => stream,
73            Err(e) => Box::pin(futures::stream::once(async move { Err(e) })) as OpaqueRegLeafStream<'a>
74        }
75    }).flatten());
76
77    Ok(Box::pin(stream))
78}