From 94b55711cbaa289d6ba4aa4b7f0cc8d2ad3e5506 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 30 Nov 2022 12:42:06 +0100 Subject: [PATCH] fix: use AsRef generics for pagination --- codegen/src/download_testfiles.rs | 24 ++++++------ src/client/mod.rs | 6 +++ src/client/pagination.rs | 37 ++++++++++++------- tests/youtube.rs | 61 ++++++++++++++----------------- 4 files changed, 68 insertions(+), 60 deletions(-) diff --git a/codegen/src/download_testfiles.rs b/codegen/src/download_testfiles.rs index d3a1493..18df8ef 100644 --- a/codegen/src/download_testfiles.rs +++ b/codegen/src/download_testfiles.rs @@ -208,7 +208,7 @@ async fn playlist_cont(testfiles: &Path) { .unwrap(); let rp = rp_testfile(&json_path); - playlist.videos.next(&rp.query()).await.unwrap().unwrap(); + playlist.videos.next(rp.query()).await.unwrap().unwrap(); } async fn video_details(testfiles: &Path) { @@ -246,7 +246,7 @@ async fn comments_top(testfiles: &Path) { let rp = rp_testfile(&json_path); details .top_comments - .next(&rp.query()) + .next(rp.query()) .await .unwrap() .unwrap(); @@ -266,7 +266,7 @@ async fn comments_latest(testfiles: &Path) { let rp = rp_testfile(&json_path); details .latest_comments - .next(&rp.query()) + .next(rp.query()) .await .unwrap() .unwrap(); @@ -284,7 +284,7 @@ async fn recommendations(testfiles: &Path) { let details = rp.query().video_details("ZeerrnuLi5E").await.unwrap(); let rp = rp_testfile(&json_path); - details.recommended.next(&rp.query()).await.unwrap(); + details.recommended.next(rp.query()).await.unwrap(); } async fn channel_videos(testfiles: &Path) { @@ -384,7 +384,7 @@ async fn channel_videos_cont(testfiles: &Path) { .unwrap(); let rp = rp_testfile(&json_path); - videos.content.next(&rp.query()).await.unwrap().unwrap(); + videos.content.next(rp.query()).await.unwrap().unwrap(); } async fn channel_playlists_cont(testfiles: &Path) { @@ -403,7 +403,7 @@ async fn channel_playlists_cont(testfiles: &Path) { .unwrap(); let rp = rp_testfile(&json_path); - playlists.content.next(&rp.query()).await.unwrap().unwrap(); + playlists.content.next(rp.query()).await.unwrap().unwrap(); } async fn search(testfiles: &Path) { @@ -430,7 +430,7 @@ async fn search_cont(testfiles: &Path) { let search = rp.query().search("doobydoobap").await.unwrap(); let rp = rp_testfile(&json_path); - search.items.next(&rp.query()).await.unwrap().unwrap(); + search.items.next(rp.query()).await.unwrap().unwrap(); } async fn search_playlists(testfiles: &Path) { @@ -492,7 +492,7 @@ async fn startpage_cont(testfiles: &Path) { let startpage = rp.query().startpage().await.unwrap(); let rp = rp_testfile(&json_path); - startpage.next(&rp.query()).await.unwrap(); + startpage.next(rp.query()).await.unwrap(); } async fn trending(testfiles: &Path) { @@ -541,7 +541,7 @@ async fn music_playlist_cont(testfiles: &Path) { .unwrap(); let rp = rp_testfile(&json_path); - playlist.tracks.next(&rp.query()).await.unwrap().unwrap(); + playlist.tracks.next(rp.query()).await.unwrap().unwrap(); } async fn music_playlist_related(testfiles: &Path) { @@ -562,7 +562,7 @@ async fn music_playlist_related(testfiles: &Path) { let rp = rp_testfile(&json_path); playlist .related_playlists - .next(&rp.query()) + .next(rp.query()) .await .unwrap() .unwrap(); @@ -688,7 +688,7 @@ async fn music_search_cont(testfiles: &Path) { let res = rp.query().music_search_tracks("black mamba").await.unwrap(); let rp = rp_testfile(&json_path); - res.items.next(&rp.query()).await.unwrap().unwrap(); + res.items.next(rp.query()).await.unwrap().unwrap(); } async fn music_search_suggestion(testfiles: &Path) { @@ -801,7 +801,7 @@ async fn music_radio_cont(testfiles: &Path) { let res = rp.query().music_radio("RDAMVM7nigXQS1Xb0").await.unwrap(); let rp = rp_testfile(&json_path); - res.next(&rp.query()).await.unwrap().unwrap(); + res.next(rp.query()).await.unwrap().unwrap(); } async fn music_new_albums(testfiles: &Path) { diff --git a/src/client/mod.rs b/src/client/mod.rs index 5b26b44..3b82f4f 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1164,6 +1164,12 @@ impl RustyPipeQuery { } } +impl AsRef for RustyPipeQuery { + fn as_ref(&self) -> &RustyPipeQuery { + self + } +} + /// Implement this for YouTube API response structs that need to be mapped to /// RustyPipe models. trait MapResponse { diff --git a/src/client/pagination.rs b/src/client/pagination.rs index 5ec9e7e..702b7a6 100644 --- a/src/client/pagination.rs +++ b/src/client/pagination.rs @@ -176,10 +176,11 @@ impl MapResponse> for response::MusicContinuation { } impl Paginator { - pub async fn next(&self, query: &RustyPipeQuery) -> Result, Error> { + pub async fn next>(&self, query: Q) -> Result, Error> { Ok(match &self.ctoken { Some(ctoken) => Some( query + .as_ref() .continuation(ctoken, self.endpoint, self.visitor_data.as_deref()) .await?, ), @@ -187,7 +188,7 @@ impl Paginator { }) } - pub async fn extend(&mut self, query: &RustyPipeQuery) -> Result { + pub async fn extend>(&mut self, query: Q) -> Result { match self.next(query).await { Ok(Some(paginator)) => { let mut items = paginator.items; @@ -200,11 +201,12 @@ impl Paginator { } } - pub async fn extend_pages( + pub async fn extend_pages>( &mut self, - query: &RustyPipeQuery, + query: Q, n_pages: usize, ) -> Result<(), Error> { + let query = query.as_ref(); for _ in 0..n_pages { match self.extend(query).await { Ok(false) => break, @@ -215,11 +217,12 @@ impl Paginator { Ok(()) } - pub async fn extend_limit( + pub async fn extend_limit>( &mut self, - query: &RustyPipeQuery, + query: Q, n_items: usize, ) -> Result<(), Error> { + let query = query.as_ref(); while self.items.len() < n_items { match self.extend(query).await { Ok(false) => break, @@ -232,10 +235,11 @@ impl Paginator { } impl Paginator { - pub async fn next(&self, query: &RustyPipeQuery) -> Result, Error> { + pub async fn next>(&self, query: Q) -> Result, Error> { Ok(match &self.ctoken { Some(ctoken) => Some( query + .as_ref() .video_comments(ctoken, self.visitor_data.as_deref()) .await?, ), @@ -245,9 +249,9 @@ impl Paginator { } impl Paginator { - pub async fn next(&self, query: &RustyPipeQuery) -> Result, Error> { + pub async fn next>(&self, query: Q) -> Result, Error> { Ok(match &self.ctoken { - Some(ctoken) => Some(query.playlist_continuation(ctoken).await?), + Some(ctoken) => Some(query.as_ref().playlist_continuation(ctoken).await?), None => None, }) } @@ -256,7 +260,10 @@ impl Paginator { macro_rules! paginator { ($entity_type:ty) => { impl Paginator<$entity_type> { - pub async fn extend(&mut self, query: &RustyPipeQuery) -> Result { + pub async fn extend>( + &mut self, + query: Q, + ) -> Result { match self.next(query).await { Ok(Some(paginator)) => { let mut items = paginator.items; @@ -269,11 +276,12 @@ macro_rules! paginator { } } - pub async fn extend_pages( + pub async fn extend_pages>( &mut self, - query: &RustyPipeQuery, + query: Q, n_pages: usize, ) -> Result<(), Error> { + let query = query.as_ref(); for _ in 0..n_pages { match self.extend(query).await { Ok(false) => break, @@ -284,11 +292,12 @@ macro_rules! paginator { Ok(()) } - pub async fn extend_limit( + pub async fn extend_limit>( &mut self, - query: &RustyPipeQuery, + query: Q, n_items: usize, ) -> Result<(), Error> { + let query = query.as_ref(); while self.items.len() < n_items { match self.extend(query).await { Ok(false) => break, diff --git a/tests/youtube.rs b/tests/youtube.rs index c662453..9052c7e 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -380,7 +380,7 @@ async fn playlist_cont() { playlist .videos - .extend_pages(&rp.query(), usize::MAX) + .extend_pages(rp.query(), usize::MAX) .await .unwrap(); assert!(playlist.videos.items.len() > 100); @@ -396,11 +396,7 @@ async fn playlist_cont2() { .await .unwrap(); - playlist - .videos - .extend_limit(&rp.query(), 101) - .await - .unwrap(); + playlist.videos.extend_limit(rp.query(), 101).await.unwrap(); assert!(playlist.videos.items.len() > 100); assert!(playlist.videos.count.unwrap() > 100); } @@ -461,7 +457,7 @@ async fn get_video_details() { assert!(!details.is_ccommons); assert!(details.recommended.visitor_data.is_some()); - assert_next(details.recommended, &rp.query(), 10, 2).await; + assert_next(details.recommended, rp.query(), 10, 2).await; assert_gte(details.top_comments.count.unwrap(), 700_000, "comments"); assert!(!details.top_comments.is_exhausted()); @@ -499,7 +495,7 @@ async fn get_video_details_music() { assert!(!details.is_ccommons); assert!(details.recommended.visitor_data.is_some()); - assert_next(details.recommended, &rp.query(), 10, 2).await; + assert_next(details.recommended, rp.query(), 10, 2).await; // Update(01.11.2022): comments are sometimes enabled /* @@ -548,7 +544,7 @@ async fn get_video_details_ccommons() { assert!(details.is_ccommons); assert!(details.recommended.visitor_data.is_some()); - assert_next(details.recommended, &rp.query(), 10, 2).await; + assert_next(details.recommended, rp.query(), 10, 2).await; assert_gte(details.top_comments.count.unwrap(), 2199, "comments"); assert!(!details.top_comments.is_exhausted()); @@ -673,7 +669,7 @@ async fn get_video_details_chapters() { } assert!(details.recommended.visitor_data.is_some()); - assert_next(details.recommended, &rp.query(), 10, 2).await; + assert_next(details.recommended, rp.query(), 10, 2).await; assert_gte(details.top_comments.count.unwrap(), 3200, "comments"); assert!(!details.top_comments.is_exhausted()); @@ -718,7 +714,7 @@ async fn get_video_details_live() { assert!(!details.is_ccommons); assert!(details.recommended.visitor_data.is_some()); - assert_next(details.recommended, &rp.query(), 10, 2).await; + assert_next(details.recommended, rp.query(), 10, 2).await; // No comments because livestream assert_eq!(details.top_comments.count, Some(0)); @@ -786,7 +782,7 @@ async fn get_video_comments() { let top_comments = details .top_comments - .next(&rp.query()) + .next(rp.query()) .await .unwrap() .unwrap(); @@ -805,7 +801,7 @@ async fn get_video_comments() { let latest_comments = details .latest_comments - .next(&rp.query()) + .next(rp.query()) .await .unwrap() .unwrap(); @@ -839,7 +835,7 @@ async fn channel_videos() { assert!(age_days < 60, "latest video older than 60 days"); - assert_next(channel.content, &rp.query(), 15, 2).await; + assert_next(channel.content, rp.query(), 15, 2).await; } #[tokio::test] @@ -873,7 +869,7 @@ async fn channel_shorts() { "got no shorts" ); - assert_next(channel.content, &rp.query(), 15, 1).await; + assert_next(channel.content, rp.query(), 15, 1).await; } #[tokio::test] @@ -893,7 +889,7 @@ async fn channel_livestreams() { "got no streams" ); - assert_next(channel.content, &rp.query(), 5, 1).await; + assert_next(channel.content, rp.query(), 5, 1).await; } #[tokio::test] @@ -912,7 +908,7 @@ async fn channel_playlists() { "got no playlists" ); - assert_next(channel.content, &rp.query(), 15, 1).await; + assert_next(channel.content, rp.query(), 15, 1).await; } #[tokio::test] @@ -1099,7 +1095,7 @@ async fn search() { ); assert_eq!(result.corrected_query.unwrap(), "doobydobap"); - assert_next(result.items, &rp.query(), 10, 2).await; + assert_next(result.items, rp.query(), 10, 2).await; } #[rstest] @@ -1115,7 +1111,7 @@ async fn search_filter_entity(#[case] entity: search_filter::Entity) { .await .unwrap(); - result.items.extend(&rp.query()).await.unwrap(); + result.items.extend(rp.query()).await.unwrap(); assert_gte(result.items.items.len(), 20, "items"); result.items.items.iter().for_each(|item| match item { @@ -1243,7 +1239,7 @@ async fn startpage() { // The startpage requires visitor data to fetch continuations assert!(startpage.visitor_data.is_some()); - assert_next(startpage, &rp.query(), 20, 2).await; + assert_next(startpage, rp.query(), 20, 2).await; } #[tokio::test] @@ -1321,7 +1317,7 @@ async fn music_playlist_cont() { playlist .tracks - .extend_pages(&rp.query(), usize::MAX) + .extend_pages(rp.query(), usize::MAX) .await .unwrap(); @@ -1338,11 +1334,7 @@ async fn music_playlist_related() { .await .unwrap(); - playlist - .related_playlists - .extend(&rp.query()) - .await - .unwrap(); + playlist.related_playlists.extend(rp.query()).await.unwrap(); assert_gte( playlist.related_playlists.items.len(), @@ -1571,7 +1563,7 @@ async fn music_search_tracks() { assert_eq!(album.id, "MPREb_OpHWHwyNOuY"); assert_eq!(album.name, "Black Mamba"); - assert_next(res.items, &rp.query(), 15, 2).await; + assert_next(res.items, rp.query(), 15, 2).await; } #[tokio::test] @@ -1605,7 +1597,7 @@ async fn music_search_videos() { assert_eq!(track.album, None); assert_gte(track.view_count.unwrap(), 230_000_000, "views"); - assert_next(res.items, &rp.query(), 15, 2).await; + assert_next(res.items, rp.query(), 15, 2).await; } #[tokio::test] @@ -1692,7 +1684,7 @@ async fn music_search_albums( assert_eq!(res.corrected_query, None); - assert_next(res.items, &rp.query(), 15, n_pages).await; + assert_next(res.items, rp.query(), 15, n_pages).await; } #[tokio::test] @@ -1724,7 +1716,7 @@ async fn music_search_artists_cont() { let res = rp.query().music_search_artists("band").await.unwrap(); assert_eq!(res.corrected_query, None); - assert_next(res.items, &rp.query(), 15, 2).await; + assert_next(res.items, rp.query(), 15, 2).await; } #[rstest] @@ -2000,7 +1992,7 @@ async fn music_details_not_found() { async fn music_radio_track() { let rp = RustyPipe::builder().strict().build(); let tracks = rp.query().music_radio_track("ZeerrnuLi5E").await.unwrap(); - assert_next(tracks, &rp.query(), 20, 3).await; + assert_next(tracks, rp.query(), 20, 3).await; } #[tokio::test] @@ -2030,7 +2022,7 @@ async fn music_radio_playlist() { .music_radio_playlist("PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ") .await .unwrap(); - assert_next(tracks, &rp.query(), 10, 1).await; + assert_next(tracks, rp.query(), 10, 1).await; } #[tokio::test] @@ -2121,13 +2113,14 @@ fn assert_gte(a: T, b: T, msg: &str) { assert!(a >= b, "expected {} {}, got {}", b, msg, a); } -async fn assert_next( +async fn assert_next>( paginator: Paginator, - query: &RustyPipeQuery, + query: Q, min_items: usize, n_pages: usize, ) { let mut p = paginator; + let query = query.as_ref(); assert_gte(p.items.len(), min_items, "items on page 0"); for i in 0..n_pages {