use super::identifier::QueryIdentifier;
use super::value::Query;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Queries(Vec<Query>);
impl Queries {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &Query> {
self.0.iter()
}
pub fn get(&self, name: &QueryIdentifier) -> Option<&Query> {
self.0.iter().find(|q| &q.name == name)
}
pub fn sort_by_name(&mut self) {
self.0.sort_by(|a, b| a.name.cmp(&b.name));
}
}
impl FromIterator<Query> for Queries {
fn from_iter<I: IntoIterator<Item = Query>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<'a> IntoIterator for &'a Queries {
type Item = &'a Query;
type IntoIter = std::slice::Iter<'a, Query>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
#[cfg(test)]
pub mod strategy {
use super::super::value::strategy::query;
use super::Queries;
use proptest::prelude::*;
pub fn queries() -> impl Strategy<Value = Queries> {
proptest::collection::vec(query(), 0..=6).prop_map(|v| v.into_iter().collect())
}
}
#[cfg(test)]
mod tests {
use super::super::identifier::QueryIdentifier;
use super::super::script::QueryScript;
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn sort_by_name_yields_alphabetical_order(mut qs in strategy::queries()) {
qs.sort_by_name();
let names: Vec<&str> = qs.iter().map(|q| q.name.as_str()).collect();
for w in names.windows(2) {
prop_assert!(w[0] <= w[1]);
}
}
}
fn nq(s: &str) -> Query {
Query::new(QueryIdentifier::new(s).unwrap(), QueryScript::new(""), None)
}
#[test]
fn default_and_new_are_empty() {
assert!(Queries::new().is_empty());
assert_eq!(Queries::default().len(), 0);
}
#[test]
fn from_iterator_preserves_order() {
let qs: Queries = [nq("c"), nq("a"), nq("b")].into_iter().collect();
let names: Vec<&str> = qs.iter().map(|q| q.name.as_str()).collect();
assert_eq!(names, vec!["c", "a", "b"]);
assert_eq!(qs.len(), 3);
assert!(!qs.is_empty());
}
#[test]
fn sort_by_name_orders_alphabetically() {
let mut qs: Queries = [nq("charlie"), nq("alpha"), nq("bravo")]
.into_iter()
.collect();
qs.sort_by_name();
let names: Vec<&str> = qs.iter().map(|q| q.name.as_str()).collect();
assert_eq!(names, vec!["alpha", "bravo", "charlie"]);
}
#[test]
fn get_returns_the_matching_entry() {
let qs: Queries = [nq("alpha"), nq("bravo")].into_iter().collect();
let found = qs.get(&QueryIdentifier::new("bravo").unwrap()).unwrap();
assert_eq!(found.name.as_str(), "bravo");
}
#[test]
fn get_returns_none_when_absent() {
let qs: Queries = [nq("alpha")].into_iter().collect();
assert!(qs.get(&QueryIdentifier::new("missing").unwrap()).is_none());
}
#[test]
fn into_iterator_for_ref_yields_each_query() {
let qs: Queries = [nq("a"), nq("b")].into_iter().collect();
let collected: Vec<&str> = (&qs).into_iter().map(|q| q.name.as_str()).collect();
assert_eq!(collected, vec!["a", "b"]);
}
}