use reqwest::Response; use crate::http_proxy::HttpRequestBuilder; pub trait PageFormatter { fn format_n(&self, n: usize) -> String; } pub trait PageIndicator { fn is_last_page(&self, content: &str, next_page: usize) -> bool; } #[derive(thiserror::Error, Debug)] pub enum PagedError { #[error("reqwest error")] Reqwest(#[from] reqwest::Error), } pub struct Paged { next_page: usize, page_indicator: T, } impl Paged { pub fn new(init_page: usize, page_indicator: T) -> Self { Self { next_page: init_page, page_indicator, } } } impl Paged where T: PageFormatter, { pub async fn next(&mut self, client: &C) -> Result where C: HttpRequestBuilder, { let url = self.page_indicator.format_n(self.next_page); let content = client .get_builder(&url) .send() .await .and_then(Response::error_for_status)? .text() .await?; self.next_page += 1; Ok(content) } } impl Paged where T: PageFormatter + PageIndicator, { /// pages returns at least one element if it is Ok pub async fn pages(&mut self, client: &C) -> Result, PagedError> where C: HttpRequestBuilder, { let mut results = Vec::new(); loop { let content = self.next(client).await?; let terminated = self.page_indicator.is_last_page(&content, self.next_page); results.push(content); if terminated { return Ok(results); } } } }