1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! This module exports a generic invariant of http uri that has query

use crate::{define_http_uri_invariant, HttpUri};

/// An enum of requirements for a http uri to be with query.
#[derive(Debug, strum_macros::Display, Clone, PartialEq)]
pub enum HttpUriWithQueryRequirement {
    #[strum(serialize = "Uri must have query")]
    UriMustHaveQuery,
}

fn detect_any_violated_requirement(uri: &HttpUri<'_>) -> Option<HttpUriWithQueryRequirement> {
    // Ensure uri has query
    if !uri.has_query() {
        return Some(HttpUriWithQueryRequirement::UriMustHaveQuery);
    }
    None
}

define_http_uri_invariant!(
    /// A http uri, that has query part.
    HttpUriWithQuery,
    HttpUriWithQueryRequirement,
    HttpUriWithQueryRequirementViolation,
    detect_any_violated_requirement,
);

#[cfg(test)]
pub mod test_try_from {
    use std::borrow::Cow;

    use claim::{assert_err, assert_ok};
    use rstest::rstest;

    use super::*;

    fn try_uri_with_query(
        uri_str: &'static str,
    ) -> Result<
        HttpUriWithQuery<'static, HttpUri<'static>>,
        HttpUriWithQueryRequirementViolation<'static, HttpUri<'static>>,
    > {
        let http_uri = HttpUri::try_from(uri_str).unwrap();
        Cow::<'static, HttpUri<'static>>::Owned(http_uri).try_into()
    }

    #[rstest]
    #[case("http://example.org/path/to/a#abc")]
    #[case("http://example.org/")]
    #[case("https://example.org/path/to/a/")]
    #[trace]
    fn http_uri_with_out_query_will_be_rejected(#[case] uri_str: &'static str) {
        HttpUriWithQueryRequirement::UriMustHaveQuery
            .assert_violation(assert_err!(try_uri_with_query(uri_str)))
    }

    #[rstest]
    #[case("http://example.org?")]
    #[case("http://example.org/?")]
    #[case("http://localhost/?q1")]
    #[case("http://example.org/path/to/a?q2")]
    #[case("https://example.org/path/to/a/?abc#f1")]
    #[trace]
    fn http_uri_with_query_will_be_accepted(#[case] uri_str: &'static str) {
        assert_ok!(try_uri_with_query(uri_str));
    }
}