cmd_wrk_parser/type_parsers/
std.rs

1use std::net::IpAddr;
2use std::str::FromStr;
3use std::time::Duration;
4
5use lazy_static::lazy_static;
6
7use crate::{TypeParser, Error, TypeParseResult, utils};
8use regex::Regex;
9
10lazy_static! {
11    static ref DURATION_FMT_1: Regex = Regex::new(
12        r"((?P<Hour>\d{1,4}):)?(?P<Minute>\d{1,2}):(?P<Second>\d{1,2})(\.(?P<Milli>\d{1,3}))?"
13    ).unwrap();
14
15    static ref DURATION_FMT_2: Regex = Regex::new(r"(\d{1,4})(y|M|w|d|h|m|s|ms|ns)").unwrap();
16}
17
18pub struct IpParser;
19
20impl TypeParser for IpParser {
21    type Type = IpAddr;
22    type Context = ();
23
24    fn parse(&self, _ctx: &Self::Context, src: &str) -> TypeParseResult<Self::Type> {
25        let s = match utils::take_until_whitespace(src) {
26            Some(s) => s,
27            None => return Err(Error::UnexpectedToken(0)),
28        };
29
30        let val = IpAddr::from_str(s)?;
31
32        Ok((val, s.len()))
33    }
34}
35
36pub struct DurationParser;
37
38impl TypeParser for DurationParser {
39    type Type = Duration;
40    type Context = ();
41
42    fn parse(&self, _ctx: &Self::Context, src: &str) -> TypeParseResult<Self::Type> {
43        let mut out = Duration::new(0, 0);
44
45        if let Some(c) = DURATION_FMT_1.captures(src) {
46            if let Some(hour) = c.name("Hour") {
47                out += Duration::from_secs(u64::from_str(hour.as_str())? * 3600);
48            }
49
50            if let Some(min) = c.name("Minute") {
51                out += Duration::from_secs(u64::from_str(min.as_str())? * 60);
52            }
53
54            if let Some(sec) = c.name("Second") {
55                out += Duration::from_secs(u64::from_str(sec.as_str())?);
56            }
57
58            if let Some(ms) = c.name("Milli") {
59                out += Duration::from_millis(u64::from_str(ms.as_str())?);
60            }
61
62            let len = c[0].len();
63
64            return Ok((out, len))
65        }
66
67        let mut counter = 0u8;
68        let mut end: usize = 0;
69
70        for (i, c) in DURATION_FMT_2.captures_iter(src).enumerate() {
71            if counter == 0 && i == 0 {
72                continue
73            } else { counter += 1 }
74
75            let mut val = u64::from_str(c.get(1).unwrap().as_str())?;
76
77            match c.get(2).unwrap().as_str() {
78                "y"  => val *= 1_000_000 * 1_000 * 60 * 60 * 24 * 30 * 12,
79                "M"  => val *= 1_000_000 * 1_000 * 60 * 60 * 24 * 30,
80                "w"  => val *= 1_000_000 * 1_000 * 60 * 60 * 24 * 7,
81                "d"  => val *= 1_000_000 * 1_000 * 60 * 60 * 24,
82                "h"  => val *= 1_000_000 * 1_000 * 60 * 60,
83                "m"  => val *= 1_000_000 * 1_000 * 60,
84                "s"  => val *= 1_000_000 * 1_000,
85                "ms" => val *= 1_000_000,
86                "ns" => (),
87                _ => unreachable!(),
88            }
89
90            out += Duration::from_nanos(val);
91
92            end = c[0].len();
93        }
94
95        if counter > 0 {
96            Ok((out, end))
97        } else {
98            Err(Error::InvalidFormat(String::from("unable to process duration")))
99        }
100    }
101}
102
103pub struct StringParser;
104
105impl TypeParser for StringParser {
106    type Type = String;
107    type Context = ();
108
109    fn parse(&self, _ctx: &Self::Context, src: &str) -> TypeParseResult<Self::Type> where
110    {
111        let s = if let Some(s) = utils::take_until_close_quote(src) { s }
112            else { utils::take_until_whitespace(src).unwrap() };
113
114        Ok((String::from(s), s.len()))
115    }
116}