cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
use super::description::QueryDescription;
use super::identifier::QueryIdentifier;
use super::script::QueryScript;

/// A query as the domain sees it: an identifier, its script body, and
/// an optional human-facing description. The description is carried as
/// data — the adapter decodes it from the script's surface format, the
/// domain never re-parses the body.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Query {
    pub name: QueryIdentifier,
    pub script: QueryScript,
    pub description: Option<QueryDescription>,
}

impl Query {
    pub fn new(
        name: QueryIdentifier,
        script: QueryScript,
        description: Option<QueryDescription>,
    ) -> Self {
        Self {
            name,
            script,
            description,
        }
    }
}

#[cfg(test)]
pub mod strategy {
    use super::super::description::strategy::query_description;
    use super::super::identifier::strategy::query_identifier;
    use super::super::script::strategy::query_script;
    use super::Query;
    use proptest::prelude::*;

    prop_compose! {
        pub fn query()(
            name in query_identifier(),
            script in query_script(),
            description in proptest::option::of(query_description()),
        ) -> Query {
            Query::new(name, script, description)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn round_trip_fields(q in strategy::query()) {
            let again = Query::new(q.name.clone(), q.script.clone(), q.description.clone());
            prop_assert_eq!(again, q);
        }
    }

    fn name(s: &str) -> QueryIdentifier {
        QueryIdentifier::new(s).unwrap()
    }

    #[test]
    fn carries_an_optional_description() {
        let q = Query::new(
            name("counts"),
            QueryScript::new("?[n] := n = 1\n"),
            Some(QueryDescription::new("number of issues")),
        );
        assert_eq!(
            q.description.as_ref().map(|d| d.as_str()),
            Some("number of issues")
        );
    }

    #[test]
    fn description_is_optional() {
        let q = Query::new(name("counts"), QueryScript::new("?[n] := n = 1\n"), None);
        assert!(q.description.is_none());
    }
}