1use nom::bytes::complete::take;
4use nom::combinator::map_res;
5use nom::IResult;
6
7#[doc(hidden)]
8pub mod export {
9 pub use core::{fmt, mem, ptr};
10}
11
12#[macro_export]
14macro_rules! newtype_enum (
15 (@collect_impl, $name:ident, $($key:ident = $val:expr),* $(,)*) => {
16 $( pub const $key : $name = $name($val); )*
17 };
18
19 (@collect_disp, $name:ident, $f:ident, $m:expr, $($key:ident = $val:expr),* $(,)*) => {
20 match $m {
21 $( $val => write!($f, stringify!{$key}), )*
22 n => write!($f, "{}({} / 0x{:x})", stringify!{$name}, n, n)
23 }
24 };
25
26 (impl $name:ident {$($body:tt)*}) => (
28 #[allow(non_upper_case_globals)]
29 impl $name {
30 newtype_enum!{@collect_impl, $name, $($body)*}
31 }
32 );
33
34 (impl display $name:ident {$($body:tt)*}) => (
36 newtype_enum!(impl $name { $($body)* });
37
38 impl $crate::export::fmt::Display for $name {
39 fn fmt(&self, f: &mut $crate::export::fmt::Formatter) -> $crate::export::fmt::Result {
40 newtype_enum!(@collect_disp, $name, f, self.0, $($body)*)
41 }
42 }
43 );
44
45 (impl debug $name:ident {$($body:tt)*}) => (
47 newtype_enum!(impl display $name { $($body)* });
48
49 impl $crate::export::fmt::Debug for $name {
50 fn fmt(&self, f: &mut $crate::export::fmt::Formatter) -> $crate::export::fmt::Result {
51 write!(f, "{}", self)
52 }
53 }
54 );
55);
56
57#[macro_export]
61macro_rules! custom_check (
62 ($i:expr, $cond:expr, $err:expr) => (
63 {
64 if $cond {
65 Err(::nom::Err::Error($err))
66 } else {
67 Ok(($i, ()))
68 }
69 }
70 );
71);
72
73#[macro_export]
77macro_rules! error_if (
78 ($i:expr, $cond:expr, $err:expr) => (
79 {
80 use nom::error_position;
81 if $cond {
82 Err(::nom::Err::Error(error_position!($i, $err)))
83 } else {
84 Ok(($i, ()))
85 }
86 }
87 );
88);
89
90#[macro_export]
94#[deprecated(since = "2.0.0")]
95macro_rules! empty (
96 ($i:expr,) => (
97 {
98 use nom::eof;
99 eof!($i,)
100 }
101 );
102);
103
104#[deprecated(since = "3.0.1", note = "please use `be_var_u64` instead")]
105pub fn bytes_to_u64(s: &[u8]) -> Result<u64, &'static str> {
110 let mut u: u64 = 0;
111
112 if s.is_empty() {
113 return Err("empty");
114 };
115 if s.len() > 8 {
116 return Err("overflow");
117 }
118 for &c in s {
119 let u1 = u << 8;
120 u = u1 | (c as u64);
121 }
122
123 Ok(u)
124}
125
126#[macro_export]
128macro_rules! parse_hex_to_u64 (
129 ( $i:expr, $size:expr ) => {
130 map_res(take($size as usize), $crate::combinator::be_var_u64)($i)
131 };
132);
133
134#[deprecated(since = "0.5.0", note = "please use `be_u24` instead")]
136#[allow(deprecated)]
137#[inline]
138pub fn parse_uint24(i: &[u8]) -> IResult<&[u8], u64> {
139 map_res(take(3usize), bytes_to_u64)(i)
140}
141
142#[macro_export]
146macro_rules! flat_take (
147 ($i:expr, $len:expr, $f:ident) => ({
148 if $i.len() < $len { Err(::nom::Err::Incomplete(::nom::Needed::new($len))) }
149 else {
150 let taken = &$i[0..$len];
151 let rem = &$i[$len..];
152 match $f(taken) {
153 Ok((_,res)) => Ok((rem,res)),
154 Err(e) => Err(e)
155 }
156 }
157 });
158 ($i:expr, $len:expr, $submac:ident!( $($args:tt)*)) => ({
159 if $i.len() < $len { Err(::nom::Err::Incomplete(::nom::Needed::new($len))) }
160 else {
161 let taken = &$i[0..$len];
162 let rem = &$i[$len..];
163 match $submac!(taken, $($args)*) {
164 Ok((_,res)) => Ok((rem,res)),
165 Err(e) => Err(e)
166 }
167 }
168 });
169);
170
171#[macro_export]
174macro_rules! upgrade_error (
175 ($i:expr, $submac:ident!( $($args:tt)*) ) => ({
176 upgrade_error!( $submac!( $i, $($args)* ) )
177 });
178 ($i:expr, $f:expr) => ({
179 upgrade_error!( call!($i, $f) )
180 });
181 ($e:expr) => ({
182 match $e {
183 Ok(o) => Ok(o),
184 Err(::nom::Err::Error(e)) => Err(::nom::Err::Error(e.into())),
185 Err(::nom::Err::Failure(e)) => Err(::nom::Err::Failure(e.into())),
186 Err(::nom::Err::Incomplete(i)) => Err(::nom::Err::Incomplete(i)),
187 }
188 });
189);
190
191#[macro_export]
194macro_rules! upgrade_error_to (
195 ($i:expr, $ty:ty, $submac:ident!( $($args:tt)*) ) => ({
196 upgrade_error_to!( $ty, $submac!( $i, $($args)* ) )
197 });
198 ($i:expr, $ty:ty, $f:expr) => ({
199 upgrade_error_to!( $ty, call!($i, $f) )
200 });
201 ($ty:ty, $e:expr) => ({
202 match $e {
203 Ok(o) => Ok(o),
204 Err(::nom::Err::Error(e)) => Err(::nom::Err::Error(e.into::<$ty>())),
205 Err(::nom::Err::Failure(e)) => Err(::nom::Err::Failure(e.into::<$ty>())),
206 Err(::nom::Err::Incomplete(i)) => Err(::nom::Err::Incomplete(i)),
207 }
208 });
209);
210
211#[macro_export]
213macro_rules! q {
214 ($i:expr, $x:expr) => {{
215 Ok(($i, $x))
216 }};
217}
218
219#[macro_export]
222macro_rules! align_n2 {
223 ($x:expr, $n:expr) => {
224 ($x + ($n - 1)) & !($n - 1)
225 };
226}
227
228#[macro_export]
230macro_rules! align32 {
231 ($x:expr) => {
232 $crate::align_n2!($x, 4)
233 };
234}
235
236#[cfg(test)]
237mod tests {
238 use nom::error::ErrorKind;
239 use nom::number::streaming::{be_u16, be_u32};
240 use nom::{error_position, Err, IResult, Needed};
241
242 #[test]
243 fn test_error_if() {
244 let empty = &b""[..];
245 let res: IResult<&[u8], ()> = error_if!(empty, true, ErrorKind::Tag);
246 assert_eq!(res, Err(Err::Error(error_position!(empty, ErrorKind::Tag))));
247 }
248
249 #[test]
250 fn test_newtype_enum() {
251 #[derive(Debug, PartialEq, Eq)]
252 struct MyType(pub u8);
253
254 newtype_enum! {
255 impl display MyType {
256 Val1 = 0,
257 Val2 = 1
258 }
259 }
260
261 assert_eq!(MyType(0), MyType::Val1);
262 assert_eq!(MyType(1), MyType::Val2);
263
264 assert_eq!(format!("{}", MyType(0)), "Val1");
265 assert_eq!(format!("{}", MyType(4)), "MyType(4 / 0x4)");
266 }
267 #[test]
268 fn test_flat_take() {
269 let input = &[0x00, 0x01, 0xff];
270 let res: IResult<&[u8], u16> = flat_take!(input, 2, be_u16);
272 assert_eq!(res, Ok((&input[2..], 0x0001)));
273 let res: IResult<&[u8], u16> = flat_take!(input, 3, be_u16);
275 assert_eq!(res, Ok((&b""[..], 0x0001)));
276 let res: IResult<&[u8], u32> = flat_take!(input, 2, be_u32);
278 assert_eq!(res, Err(Err::Incomplete(Needed::new(2))));
279 let res: IResult<&[u8], u16> = flat_take!(input, 2, be_u16);
281 assert_eq!(res, Ok((&input[2..], 0x0001)));
282 }
283
284 #[test]
285 fn test_q() {
286 let empty = &b""[..];
287 let res: IResult<&[u8], &str, ErrorKind> = q!(empty, "test");
288 assert_eq!(res, Ok((empty, "test")));
289 }
290
291 #[test]
292 fn test_align32() {
293 assert_eq!(align32!(3), 4);
294 assert_eq!(align32!(4), 4);
295 assert_eq!(align32!(5), 8);
296 assert_eq!(align32!(5u32), 8);
297 assert_eq!(align32!(5i32), 8);
298 assert_eq!(align32!(5usize), 8);
299 }
300}