#[derive(Debug, Clone, Default)]
pub struct Query {
pub kind_filter: Option<String>,
pub tag_filter: Vec<String>,
pub limit: Option<usize>,
pub offset: usize,
}
impl Query {
pub fn new() -> Self {
Self::default()
}
pub fn kind(mut self, k: impl Into<String>) -> Self {
self.kind_filter = Some(k.into());
self
}
pub fn tag(mut self, t: impl Into<String>) -> Self {
self.tag_filter.push(t.into());
self
}
pub fn limit(mut self, n: usize) -> Self {
self.limit = Some(n);
self
}
pub fn offset(mut self, n: usize) -> Self {
self.offset = n;
self
}
}
#[derive(Debug, Clone)]
pub struct QueryResult<T> {
pub items: Vec<T>,
pub total: usize,
pub offset: usize,
}
impl<T> QueryResult<T> {
pub fn new(items: Vec<T>, total: usize, offset: usize) -> Self {
Self { items, total, offset }
}
pub fn empty() -> Self {
Self { items: Vec::new(), total: 0, offset: 0 }
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn query_builder_sets_fields() {
let q = Query::new().kind("Source").tag("a").tag("b").limit(10).offset(5);
assert_eq!(q.kind_filter.as_deref(), Some("Source"));
assert_eq!(q.tag_filter, vec!["a", "b"]);
assert_eq!(q.limit, Some(10));
assert_eq!(q.offset, 5);
}
#[test]
fn query_default_is_unconstrained() {
let q = Query::new();
assert!(q.kind_filter.is_none());
assert!(q.tag_filter.is_empty());
assert!(q.limit.is_none());
assert_eq!(q.offset, 0);
}
#[test]
fn query_result_len_and_empty() {
let r: QueryResult<i32> = QueryResult::new(vec![1, 2, 3], 10, 0);
assert_eq!(r.len(), 3);
assert!(!r.is_empty());
let e: QueryResult<i32> = QueryResult::empty();
assert!(e.is_empty());
}
}