use crate::error::Error;
use crate::generated::types::AdvancedSearchResult;
pub use crate::generated::services::search::*;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct SearchParams {
pub query: String,
pub page: u32,
pub required: String,
pub any: String,
pub none: String,
pub exact_phrase: String,
pub from: String,
pub to: String,
pub subject: String,
pub date: String,
pub r#in: String,
pub label: String,
pub attachment: String,
}
#[derive(Debug, Clone, Default, PartialEq)]
#[non_exhaustive]
pub struct SearchResults {
pub result: AdvancedSearchResult,
pub next_page: Option<u32>,
}
impl Search<'_> {
pub async fn search(&self, params: &SearchParams) -> Result<AdvancedSearchResult, Error> {
Ok(self.search_page(params).await?.result)
}
pub async fn search_page(&self, params: &SearchParams) -> Result<SearchResults, Error> {
let page = self.advanced(&refinements(params)).await?;
let next_page = page.next_page().and_then(|page| page.parse().ok());
Ok(SearchResults {
result: page.into_inner(),
next_page,
})
}
}
fn refinements(params: &SearchParams) -> AdvancedSearchParams {
let mut advanced = AdvancedSearchParams {
q: optional(¶ms.query),
page: None,
refine_from: optional(¶ms.from),
refine_to: optional(¶ms.to),
refine_subject: optional(¶ms.subject),
refine_exact_phrase: optional(¶ms.exact_phrase),
refine_required: optional(¶ms.required),
refine_any: optional(¶ms.any),
refine_none: optional(¶ms.none),
refine_date: optional(¶ms.date),
refine_in: optional(¶ms.r#in),
refine_label: optional(¶ms.label),
refine_attachment: optional(¶ms.attachment),
};
if params.page > 1 {
advanced.page = Some(params.page.to_string());
}
advanced
}
fn optional(value: &str) -> Option<String> {
if value.is_empty() {
None
} else {
Some(value.to_string())
}
}