use futures::Stream;
use serde::{Deserialize, Serialize};
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PaginatedResponse<T> {
pub page: u32,
pub results: Vec<T>,
pub total_pages: u32,
pub total_results: u32,
}
impl<T> PaginatedResponse<T> {
pub fn new(page: u32, results: Vec<T>, total_pages: u32, total_results: u32) -> Self {
Self {
page,
results,
total_pages,
total_results,
}
}
pub fn has_next_page(&self) -> bool {
self.page < self.total_pages
}
pub fn next_page(&self) -> Option<u32> {
if self.has_next_page() {
Some(self.page + 1)
} else {
None
}
}
}
pub fn into_stream<T, E, F, Fut>(fetch_page: F) -> impl Stream<Item = Result<T, E>>
where
T: 'static,
E: 'static,
F: Fn(u32) -> Fut + 'static,
Fut: std::future::Future<Output = Result<PaginatedResponse<T>, E>> + 'static,
{
async_stream::try_stream! {
let mut page = 1u32;
loop {
let response = fetch_page(page).await?;
let has_next = response.has_next_page();
for item in response.results {
yield item;
}
if !has_next {
break;
}
page += 1;
}
}
}