uri_parsing_rs/parser/parsers/
hier_part_parsers.rs

1use nom::bytes::complete::tag;
2use nom::combinator::opt;
3use nom::sequence::{preceded, tuple};
4
5use crate::ast::authority::Authority;
6use crate::ast::path::Path;
7use crate::parser::parsers::{authority_parsers, Elms, path_parsers, UResult};
8
9// hier-part     = "//" authority path-abempty
10// / path-absolute
11// / path-rootless
12// / path-empty
13#[inline]
14pub fn hier_part(i: Elms) -> UResult<Elms, (Option<Authority>, Path)> {
15  if let (i, Some((authority, path))) = opt(preceded(
16    tag("//"),
17    tuple((authority_parsers::authority, path_parsers::path_abempty)),
18  ))(i.clone())?
19  {
20    Ok((i, (Some(authority), path)))
21  } else {
22    log::debug!("path_without_abempty = {}", i.clone());
23    let (i, path) = path_parsers::path_without_abempty(i)?;
24    Ok((i, (None, path)))
25  }
26}
27
28#[cfg(test)]
29pub mod gens {
30  use prop_check_rs::gen::{Gen, Gens};
31
32  use crate::parser::parsers::authority_parsers::gens::authority_gen;
33  use crate::parser::parsers::path_parsers::gens::*;
34
35  pub fn hier_part_gen() -> Gen<Pair<String, Option<bool>>> {
36    let gen1 = || {
37      authority_gen().bind(move |authority| {
38        path_abempty_str_gen().fmap(move |path_abempty| format!("//{}{}", authority, path_abempty))
39      })
40    };
41    let gen2 = || {
42      path_str_without_abempty_gen().fmap(|Pair(p1, p2)| {
43        println!("p1 = {}", p1);
44        Pair(p2, Some(p1 == "empty_path".to_string()))
45      })
46    };
47    Gens::one_bool().bind(move |b| {
48      if b {
49        gen1().fmap(|s| Pair(s, None))
50      } else {
51        gen2()
52      }
53    })
54  }
55}
56
57#[cfg(test)]
58mod tests {
59  use std::env;
60
61  use anyhow::Result;
62  use prop_check_rs::prop;
63  use prop_check_rs::prop::TestCases;
64  use prop_check_rs::rng::RNG;
65
66  use super::*;
67  use super::gens::*;
68  use crate::parser::parsers::path_parsers::gens::Pair;
69
70  const TEST_COUNT: TestCases = 100;
71
72  fn init() {
73    env::set_var("RUST_LOG", "debug");
74    let _ = env_logger::builder().is_test(true).try_init();
75  }
76
77  #[test]
78  fn test_hier_part() -> Result<()> {
79    init();
80    let mut counter = 0;
81    let prop = prop::for_all(
82      || hier_part_gen(),
83      move |Pair(s, _b)| {
84        counter += 1;
85        log::debug!("{:>03}, hier_part = {}", counter, s);
86        let (_, (authority, path)) = hier_part(Elms::new(s.as_bytes())).ok().unwrap();
87        let sa = authority
88          .map(|e| format!("//{}", e))
89          .unwrap_or("".to_string());
90        let sp = path.to_string();
91        let sap = format!("{}{}", sa, sp);
92        assert_eq!(sap, s);
93        true
94      },
95    );
96    prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
97  }
98}