use crate::db::Item;
use crate::{Game, GameFilter, SearchType};
use paste::paste;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
macro_rules! filter_games_by {
($field:ident) => {
paste! {
pub fn [<filter_games_by_ $field>](self, field: &str, search_type: &SearchType) -> QueryResult<&'a Game> {
let items = GameFilter::default().[<set_ $field>](field).filter_games(self.items, search_type);
QueryResult::new(items)
}
}
};
}
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct QueryResult<T> {
pub count: usize,
pub items: Vec<T>,
}
impl<T: Ord> QueryResult<T> {
pub fn new(mut items: Vec<T>) -> Self {
items.sort();
Self {
count: items.len(),
items,
}
}
pub fn get(&self, index: usize) -> Option<&T> {
self.items.get(index)
}
pub fn into_inner(self) -> Vec<T> {
self.items
}
}
impl<'a> QueryResult<&'a Item> {
pub fn get_item_by_name<'b>(self, name: &'b str) -> Option<&'a Item> {
let mut items: Vec<&Item> = self.items.into_iter().filter(|a| a.eq(&name)).collect();
items.pop()
}
pub fn filter_items_by_name<'b>(self, name: &'b str) -> QueryResult<&'a Item> {
let items: Vec<&Item> = self
.items
.into_iter()
.filter(|a| a.to_lowercase().contains(&name.to_lowercase()))
.collect();
QueryResult::new(items)
}
}
impl<'a> QueryResult<&'a Game> {
pub fn get_game_by_name(self, name: &str, search_type: &SearchType) -> Option<&'a Game> {
let mut items = GameFilter::default()
.set_name(name)
.filter_games(self.items, search_type);
items.sort();
items.pop()
}
filter_games_by!(name);
filter_games_by!(runtime);
filter_games_by!(year);
filter_games_by!(engine);
filter_games_by!(dev);
filter_games_by!(publi);
filter_games_by!(genre);
filter_games_by!(tag);
}
impl<T> IntoIterator for QueryResult<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
#[cfg(test)]
mod query_results_tests {
use crate::QueryResult;
#[test]
fn test_new() {
let v = vec!["item1".to_string(), "item2".to_string()];
let v2 = v.clone();
let qr = QueryResult::new(v);
assert_eq!(qr.items, v2);
assert_eq!(qr.count, 2);
}
}