uri_parsing_rs/parser/parsers/
user_info_parsers.rs1use nom::branch::alt;
2use nom::character::complete;
3use nom::combinator::{map, opt};
4use nom::error::context;
5use nom::multi::many1;
6use nom::sequence::{preceded, tuple};
7
8use crate::ast::user_info::UserInfo;
9use crate::parser::parsers::{Elms, UResult};
10use crate::parser::parsers::basic_parsers::{pct_encoded, sub_delims, unreserved};
11
12#[inline]
13fn code_point(i: Elms) -> UResult<Elms, String> {
14 map(
15 many1(alt((
16 map(unreserved, |c| c.into()),
17 pct_encoded,
18 map(sub_delims, |c| c.into()),
19 ))),
20 |sl| sl.into_iter().collect(),
21 )(i)
22}
23
24#[inline]
26pub(crate) fn user_info(i: Elms) -> UResult<Elms, UserInfo> {
27 context(
28 "user_info",
29 map(
30 tuple((code_point, opt(preceded(complete::char(':'), code_point)))),
31 |(user_name, password)| (user_name.as_str(), password.as_ref().map(|s| s.as_str())).into(),
32 ),
33 )(i)
34}
35
36#[cfg(test)]
37pub mod gens {
38 use prop_check_rs::gen::{Gen, Gens};
39
40 use crate::parser::parsers::basic_parsers::gens::*;
41
42 pub fn user_info_gen() -> Gen<String> {
43 let gen = || {
44 rep_str_gen(1, 5, || {
45 Gens::choose_u8(1, 3).bind(|n| match n {
46 1 => unreserved_str_gen(1),
47 2 => pct_encoded_str_gen(),
48 3 => sub_delims_str_gen(1),
49 x => panic!("x = {}", x),
50 })
51 })
52 };
53 Gens::one_bool().bind(move |b| {
54 if b {
55 gen().bind(move |s1| gen().fmap(move |s2| format!("{}:{}", s1, s2)))
56 } else {
57 gen().fmap(|s| format!("{}", s))
58 }
59 })
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use std::env;
66
67 use anyhow::Result;
68 use prop_check_rs::prop;
69 use prop_check_rs::prop::TestCases;
70 use prop_check_rs::rng::RNG;
71
72 use super::*;
73 use super::gens::*;
74
75 const TEST_COUNT: TestCases = 100;
76
77 fn init() {
78 env::set_var("RUST_LOG", "debug");
79 let _ = env_logger::builder().is_test(true).try_init();
80 }
81
82 #[test]
83 fn test_user_info() -> Result<()> {
84 init();
85 let mut counter = 0;
86 let prop = prop::for_all(
87 || user_info_gen(),
88 move |s| {
89 counter += 1;
90 log::debug!("{:>03}, user_info = {}", counter, s);
91 let (_, r) = user_info(Elms::new(s.as_bytes())).ok().unwrap();
92 assert_eq!(r.to_string(), s);
93 true
94 },
95 );
96 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
97 }
98}