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