#[derive(Debug, Default, Clone, bon::Builder)]
#[builder(on(String, into))]
pub struct ItemListParams {
pub q: Option<String>,
pub qmode: Option<String>,
pub tag: Option<String>,
#[builder(name = "item_type")]
pub item_type: Option<String>,
#[builder(name = "item_key")]
pub item_key: Option<String>,
pub since: Option<u64>,
pub sort: Option<String>,
pub direction: Option<String>,
pub limit: Option<u32>,
pub start: Option<u32>,
pub format: Option<String>,
pub include: Option<String>,
pub style: Option<String>,
#[builder(name = "include_trashed")]
pub include_trashed: Option<bool>,
}
impl ItemListParams {
pub(crate) fn to_query_pairs(&self) -> Vec<(&str, String)> {
let mut pairs = Vec::new();
if let Some(v) = &self.q {
pairs.push(("q", v.clone()));
}
if let Some(v) = &self.qmode {
pairs.push(("qmode", v.clone()));
}
if let Some(v) = &self.tag {
pairs.push(("tag", v.clone()));
}
if let Some(v) = &self.item_type {
pairs.push(("itemType", v.clone()));
}
if let Some(v) = &self.item_key {
pairs.push(("itemKey", v.clone()));
}
if let Some(v) = self.since {
pairs.push(("since", v.to_string()));
}
if let Some(v) = &self.sort {
pairs.push(("sort", v.clone()));
}
if let Some(v) = &self.direction {
pairs.push(("direction", v.clone()));
}
if let Some(v) = self.limit {
pairs.push(("limit", v.to_string()));
}
if let Some(v) = self.start {
pairs.push(("start", v.to_string()));
}
if let Some(v) = &self.format {
pairs.push(("format", v.clone()));
}
if let Some(v) = &self.include {
pairs.push(("include", v.clone()));
}
if let Some(v) = &self.style {
pairs.push(("style", v.clone()));
}
if let Some(v) = self.include_trashed {
pairs.push(("includeTrashed", if v { "1" } else { "0" }.into()));
}
pairs
}
}
#[derive(Debug, Default, Clone, bon::Builder)]
#[builder(on(String, into))]
pub struct CollectionListParams {
pub sort: Option<String>,
pub direction: Option<String>,
pub limit: Option<u32>,
pub start: Option<u32>,
}
impl CollectionListParams {
pub(crate) fn to_query_pairs(&self) -> Vec<(&str, String)> {
let mut pairs = Vec::new();
if let Some(v) = &self.sort {
pairs.push(("sort", v.clone()));
}
if let Some(v) = &self.direction {
pairs.push(("direction", v.clone()));
}
if let Some(v) = self.limit {
pairs.push(("limit", v.to_string()));
}
if let Some(v) = self.start {
pairs.push(("start", v.to_string()));
}
pairs
}
}
#[derive(Debug, Default, Clone, bon::Builder)]
#[builder(on(String, into))]
pub struct TagListParams {
pub q: Option<String>,
pub qmode: Option<String>,
pub limit: Option<u32>,
pub start: Option<u32>,
pub sort: Option<String>,
pub direction: Option<String>,
}
impl TagListParams {
pub(crate) fn to_query_pairs(&self) -> Vec<(&str, String)> {
let mut pairs = Vec::new();
if let Some(v) = &self.q {
pairs.push(("q", v.clone()));
}
if let Some(v) = &self.qmode {
pairs.push(("qmode", v.clone()));
}
if let Some(v) = self.limit {
pairs.push(("limit", v.to_string()));
}
if let Some(v) = self.start {
pairs.push(("start", v.to_string()));
}
if let Some(v) = &self.sort {
pairs.push(("sort", v.clone()));
}
if let Some(v) = &self.direction {
pairs.push(("direction", v.clone()));
}
pairs
}
}
#[derive(Debug, Default, Clone, bon::Builder)]
pub struct FulltextParams {
pub since: Option<u64>,
}
impl FulltextParams {
pub(crate) fn to_query_pairs(&self) -> Vec<(&str, String)> {
let mut pairs = Vec::new();
if let Some(v) = self.since {
pairs.push(("since", v.to_string()));
}
pairs
}
}
#[derive(Debug, Clone, bon::Builder)]
pub struct DeletedParams {
pub since: u64,
}
impl DeletedParams {
pub(crate) fn to_query_pairs(&self) -> Vec<(&str, String)> {
vec![("since", self.since.to_string())]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_item_list_params_default() {
let params = ItemListParams::default();
assert!(params.q.is_none());
assert!(params.sort.is_none());
assert!(params.limit.is_none());
}
#[test]
fn test_item_list_params_builder() {
let params = ItemListParams::builder()
.q("test")
.item_type("journalArticle")
.sort("dateModified")
.direction("desc")
.limit(10)
.build();
assert_eq!(params.q.as_deref(), Some("test"));
assert_eq!(params.item_type.as_deref(), Some("journalArticle"));
assert_eq!(params.limit, Some(10));
}
#[test]
fn test_item_list_params_query_pairs() {
let params = ItemListParams::builder()
.q("test")
.item_type("book")
.limit(5)
.include_trashed(true)
.build();
let pairs = params.to_query_pairs();
assert!(pairs.contains(&("q", "test".into())));
assert!(pairs.contains(&("itemType", "book".into())));
assert!(pairs.contains(&("limit", "5".into())));
assert!(pairs.contains(&("includeTrashed", "1".into())));
}
#[test]
fn test_collection_list_params_builder() {
let params = CollectionListParams::builder()
.sort("title")
.limit(50)
.build();
assert_eq!(params.sort.as_deref(), Some("title"));
assert_eq!(params.limit, Some(50));
}
#[test]
fn test_tag_list_params_builder() {
let params = TagListParams::builder()
.q("ML")
.limit(10)
.build();
assert_eq!(params.q.as_deref(), Some("ML"));
assert_eq!(params.limit, Some(10));
}
#[test]
fn test_fulltext_params_default_empty() {
let params = FulltextParams::default();
assert!(params.to_query_pairs().is_empty());
}
#[test]
fn test_fulltext_params_since() {
let params = FulltextParams::builder().since(1380u64).build();
let pairs = params.to_query_pairs();
assert_eq!(pairs, vec![("since", "1380".into())]);
}
#[test]
fn test_deleted_params_since() {
let params = DeletedParams::builder().since(0u64).build();
let pairs = params.to_query_pairs();
assert_eq!(pairs, vec![("since", "0".into())]);
}
#[test]
fn test_deleted_params_since_nonzero() {
let params = DeletedParams::builder().since(500u64).build();
assert_eq!(params.since, 500);
let pairs = params.to_query_pairs();
assert_eq!(pairs, vec![("since", "500".into())]);
}
}