From 9fbf1da95706438359431e2ba63828eb5c53c6bf Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Tue, 15 Oct 2024 15:23:44 -0700 Subject: [PATCH] feat: add id filter to crates query Gets information about multiple crates in a single call ```rust let query = CratesQuery { ids: Some(vec!["serde", "tokio"]), ..Default::default() }; ``` --- src/async_client.rs | 25 +++++++++++++++++++++++++ src/types.rs | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/async_client.rs b/src/async_client.rs index 17ec759..c0b628b 100644 --- a/src/async_client.rs +++ b/src/async_client.rs @@ -569,6 +569,31 @@ mod test { Ok(()) } + #[tokio::test] + async fn test_crates_filter_by_ids_async() -> Result<(), Error> { + let client = build_test_client(); + + let ids = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] + .map(Into::into) + .to_vec(); + let res = client + .crates(CratesQuery { + ids: Some(ids), + per_page: 10, + ..Default::default() + }) + .await?; + + assert_eq!( + res.crates.len(), + 10, + "Expected 10 crates, actually got {}. Crates: {:#?}", + res.crates.len(), + res.crates + ); + Ok(()) + } + #[tokio::test] async fn test_crate_reverse_dependency_count_async() -> Result<(), Error> { let client = build_test_client(); diff --git a/src/types.rs b/src/types.rs index f9c717f..3d99eab 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,24 +2,24 @@ use chrono::{DateTime, NaiveDate, Utc}; use serde_derive::*; -use std::collections::HashMap; +use std::{collections::HashMap, fmt}; -/// Used to specify the sort behaviour of the `Client::crates()` method. +/// A list of errors returned by the API. #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] pub struct ApiErrors { /// Individual errors. pub errors: Vec, } -/// Used to specify the sort behaviour of the `Client::crates()` method. +/// An error returned by the API. #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] pub struct ApiError { /// Error message. pub detail: Option, } -impl std::fmt::Display for ApiError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for ApiError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", @@ -77,6 +77,8 @@ pub struct CratesQuery { pub(crate) category: Option, /// Search query string. pub(crate) search: Option, + /// List of crate ids. + pub(crate) ids: Option>, } impl CratesQuery { @@ -93,6 +95,11 @@ impl CratesQuery { if let Some(cat) = &self.category { q.append_pair("category", cat); } + if let Some(ids) = &self.ids { + for id in ids { + q.append_pair("ids[]", id); + } + } } } @@ -161,6 +168,16 @@ impl CratesQuery { pub fn set_search(&mut self, search: Option) { self.search = search; } + + /// Get a reference to the crate query's ids. + pub fn ids(&self) -> Option<&Vec> { + self.ids.as_ref() + } + + /// Set the crate query's ids. + pub fn set_ids(&mut self, ids: Option>) { + self.ids = ids; + } } impl Default for CratesQuery { @@ -172,6 +189,7 @@ impl Default for CratesQuery { user_id: None, category: None, search: None, + ids: None, } } } @@ -235,6 +253,13 @@ impl CratesQueryBuilder { self } + /// List of crate ids. + #[must_use] + pub fn ids(mut self, ids: Vec) -> Self { + self.query.ids = Some(ids); + self + } + /// Finalize the builder into a usable [`CratesQuery`]. #[must_use] pub fn build(self) -> CratesQuery {