uri_parsing_rs/parser/parsers/
scheme_parsers.rs

1use nom::{AsChar, InputTakeAtPosition, IResult};
2use nom::combinator::map;
3use nom::error::{context, ErrorKind, ParseError};
4
5use crate::ast::scheme::Scheme;
6use crate::parser::parsers::{Elms, UResult};
7
8#[inline]
9fn code_point<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
10where
11  T: InputTakeAtPosition,
12  <T as InputTakeAtPosition>::Item: AsChar,
13{
14  input.split_at_position1_complete(
15    |item| {
16      let c = item.as_char();
17      !(c == '+' || c == '-' || c == '.' || c.is_alphanumeric())
18    },
19    ErrorKind::Char,
20  )
21}
22
23#[inline]
24pub(crate) fn scheme(i: Elms) -> UResult<Elms, Scheme> {
25  context("schema", map(code_point, |s: Elms| s.into()))(i)
26}
27
28#[cfg(test)]
29pub mod gens {
30  use prop_check_rs::gen::{Gen, Gens};
31
32  use crate::parser::parsers::basic_parsers::gens::*;
33
34  pub fn scheme_gen() -> Gen<String> {
35    rep_char_gen(5, || {
36      Gens::choose_u8(1, 5).bind(|n| match n {
37        1 => alpha_char_gen(),
38        2 => digit_gen('0', '9'),
39        3 => Gen::<char>::unit(|| '+'),
40        4 => Gen::<char>::unit(|| '-'),
41        5 => Gen::<char>::unit(|| '.'),
42        x => panic!("x = {}", x),
43      })
44    })
45  }
46}
47
48#[cfg(test)]
49mod tests {
50  use std::env;
51
52  use anyhow::Result;
53  use prop_check_rs::prop;
54  use prop_check_rs::prop::TestCases;
55  use prop_check_rs::rng::RNG;
56
57  use crate::parser::parsers::Elms;
58
59  use super::*;
60  use super::gens::*;
61
62  const TEST_COUNT: TestCases = 100;
63
64  fn init() {
65    env::set_var("RUST_LOG", "debug");
66    let _ = env_logger::builder().is_test(true).try_init();
67  }
68
69  #[test]
70  fn test_scheme() -> Result<()> {
71    init();
72    let mut counter = 0;
73    let prop = prop::for_all(
74      || scheme_gen(),
75      move |s| {
76        counter += 1;
77        log::debug!("{:>03}, scheme = {}", counter, s);
78        let (_, r) = scheme(Elms::new(s.as_bytes())).ok().unwrap();
79        assert_eq!(r.to_string(), s);
80        true
81      },
82    );
83    prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
84  }
85}