1use nom::{
2 branch::alt,
3 bytes::complete::{take_until, take_while},
4 character::{complete::char as parse_char, *},
5 combinator::map_res,
6 error::{ErrorKind, ParseError},
7 IResult,
8};
9
10use std::{
11 io::{Error as IoError, ErrorKind as IoErrorKind},
12 net::Ipv4Addr,
13};
14
15pub fn slice_to_string<'a, E: ParseError<&'a [u8]>>(slice: &'a [u8]) -> Result<String, E> {
17 if slice.is_empty() {
18 Err(E::from_error_kind(slice, ErrorKind::Eof))
19 } else {
20 Ok(String::from_utf8(Vec::from(slice))
21 .map_err(|_| E::from_error_kind(slice, ErrorKind::IsNot))?)
22 }
23}
24
25pub fn slice_to_string_nullable(slice: &[u8]) -> Result<String, IoError> {
26 Ok(String::from_utf8(Vec::from(slice))
27 .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "Failed to parse utf8 string"))?)
28}
29
30pub fn parse_u16<'a, E: ParseError<&'a [u8]>>(slice: &'a [u8]) -> Result<u16, E> {
32 Ok(::std::str::from_utf8(slice)
33 .map_err(|_| E::from_error_kind(slice, ErrorKind::IsNot))?
34 .parse()
35 .map_err(|_| E::from_error_kind(slice, ErrorKind::IsNot))?)
36}
37
38pub fn parse_u8(slice: &[u8]) -> Result<u8, IoError> {
40 Ok(::std::str::from_utf8(slice)
41 .map_err(|_| {
42 IoError::new(
43 IoErrorKind::InvalidInput,
44 "Failed to parse utf8 u16 integer",
45 )
46 })?
47 .parse()
48 .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "Failed to parse u8 integer"))?)
49}
50
51pub fn parse_u32(slice: &[u8]) -> Result<u32, IoError> {
53 Ok(::std::str::from_utf8(slice)
54 .map_err(|_| {
55 IoError::new(
56 IoErrorKind::InvalidInput,
57 "Failed to parse utf8 u32 integer",
58 )
59 })?
60 .parse()
61 .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "Failed to parse u32 integer"))?)
62}
63
64pub fn parse_f32(slice: &[u8]) -> Result<f32, IoError> {
66 Ok(::std::str::from_utf8(slice)
67 .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "Failed to parse utf8 f32"))?
68 .parse()
69 .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "Failed to parse f32"))?)
70}
71
72pub fn parse_byte_vec<'a, E: ParseError<&'a [u8]>>(
74 input: &'a [u8],
75) -> IResult<&'a [u8], Vec<u8>, E> {
76 Ok((&input[input.len()..], input.to_vec()))
77}
78
79pub fn parse_ip_address<'a, E: ParseError<&'a [u8]>>(
80 input: &'a [u8],
81) -> IResult<&[u8], Ipv4Addr, E> {
82 let (input, byte1) = map_res(take_while(is_digit), parse_u8)(input)?;
83 let (input, _) = parse_char('.')(input)?;
84 let (input, byte2) = map_res(take_while(is_digit), parse_u8)(input)?;
85 let (input, _) = parse_char('.')(input)?;
86 let (input, byte3) = map_res(take_while(is_digit), parse_u8)(input)?;
87 let (input, _) = parse_char('.')(input)?;
88 let (input, byte4) = map_res(take_while(is_digit), parse_u8)(input)?;
89 Ok((input, Ipv4Addr::new(byte1, byte2, byte3, byte4)))
90}
91
92pub fn parse_string<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], String, E> {
93 map_res(take_while(is_alphanumeric), slice_to_string::<E>)(input)
94}
95
96pub fn parse_possibly_quoted_string<'a, E: ParseError<&'a [u8]>>(
97 input: &'a [u8],
98) -> IResult<&'a [u8], String, E> {
99 let alts = (parse_string::<E>, parse_quoted_string::<E>);
100 alt::<_, _, E, _>(alts)(input)
101}
102
103pub fn parse_quoted_string<'a, E: ParseError<&'a [u8]>>(
104 input: &'a [u8],
105) -> IResult<&'a [u8], String, E> {
106 let (input, _) = parse_char('"')(input)?;
107 let (input, out) = map_res(take_until("\""), slice_to_string_nullable)(input)?;
108 let (input, _) = parse_char('"')(input)?;
109 Ok((input, out))
110}
111
112pub fn is_token(chr: u8) -> bool {
122 is_alphanumeric(chr) || "-.!%*_+`'~".contains(char::from(chr))
123}