uri_rs/parser/parsers/
authority_parsers.rs

1use nom::character::complete;
2use nom::combinator::{map, opt};
3use nom::error::context;
4use nom::sequence::{preceded, terminated, tuple};
5
6use crate::ast::authority::Authority;
7use crate::parser::parsers::{Elms, host_parsers, port_parsers, UResult, user_info_parsers};
8
9#[inline]
10pub(crate) fn authority(i: Elms) -> UResult<Elms, Authority> {
11  context(
12    "authority",
13    map(
14      tuple((
15        opt(terminated(
16          user_info_parsers::user_info,
17          complete::char('@'),
18        )),
19        host_parsers::host_name,
20        opt(preceded(complete::char(':'), port_parsers::port)),
21      )),
22      |(ui, h, p)| Authority::new(h, p, ui),
23    ),
24  )(i)
25}
26
27#[cfg(test)]
28pub mod gens {
29  use prop_check_rs::gen::Gen;
30
31  use crate::parser::parsers::basic_parsers::gens::to_option;
32  use crate::parser::parsers::host_parsers::gens::host_gen;
33  use crate::parser::parsers::port_parsers::gens::port_gen;
34  use crate::parser::parsers::user_info_parsers::gens::user_info_gen;
35
36  pub fn authority_gen() -> Gen<String> {
37    let user_info_opt_gen = || to_option(|| user_info_gen());
38    let port_opt_gen = || to_option(|| port_gen());
39
40    user_info_opt_gen().bind(move |ui| {
41      host_gen()
42        .bind(move |h| {
43          port_opt_gen().fmap(move |p| {
44            let p = p.map(|s| format!(":{}", s)).unwrap_or("".to_string());
45            format!("{}{}", h, p)
46          })
47        })
48        .fmap(move |hp| {
49          let ui = ui
50            .as_ref()
51            .map(|s| format!("{}@", s))
52            .unwrap_or("".to_string());
53          format!("{}{}", ui, hp)
54        })
55    })
56  }
57}
58
59#[cfg(test)]
60mod tests {
61  use std::env;
62
63  use anyhow::Result;
64  use prop_check_rs::prop;
65  use prop_check_rs::prop::TestCases;
66  use prop_check_rs::rng::RNG;
67
68  use super::*;
69  use super::gens::*;
70
71  const TEST_COUNT: TestCases = 100;
72
73  fn init() {
74    env::set_var("RUST_LOG", "debug");
75    let _ = env_logger::builder().is_test(true).try_init();
76  }
77
78  #[test]
79  fn test_authority() -> Result<()> {
80    init();
81    let mut counter = 0;
82    let prop = prop::for_all(
83      || authority_gen(),
84      move |s| {
85        counter += 1;
86        log::debug!("{:>03}, authority = {}", counter, s);
87        let (_, authority) = authority(Elms::new(s.as_bytes())).ok().unwrap();
88        assert_eq!(authority.to_string(), s);
89        true
90      },
91    );
92    prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
93  }
94}