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 fragment

use crate::{define_http_uri_invariant, HttpUri};

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

fn detect_any_violated_requirement(uri: &HttpUri<'_>) -> Option<HttpUriWithFragmentRequirement> {
    // Ensure uri has fragment
    if !uri.has_fragment() {
        return Some(HttpUriWithFragmentRequirement::UriMustHaveFragment);
    }
    None
}

define_http_uri_invariant!(
    /// A http uri, that has fragment part.
    HttpUriWithFragment,
    HttpUriWithFragmentRequirement,
    HttpUriWithFragmentRequirementViolation,
    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_fragment(
        uri_str: &'static str,
    ) -> Result<
        HttpUriWithFragment<'static, HttpUri<'static>>,
        HttpUriWithFragmentRequirementViolation<'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?bcd")]
    #[case("http://example.org/")]
    #[case("https://example.org/path/to/a/")]
    #[trace]
    fn http_uri_with_out_fragment_will_be_rejected(#[case] uri_str: &'static str) {
        HttpUriWithFragmentRequirement::UriMustHaveFragment
            .assert_violation(assert_err!(try_uri_with_fragment(uri_str)))
    }

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