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
use nom::number::complete::{le_u8, le_u16, le_u32, le_u64, le_i16, le_i32};
use nom::IResult;
use nom_methods::call_m;
use super::GUID;
use std::cell::Cell;
named_args!(pub check_guid(guid: GUID)<GUID>,
verify!(parse_guid, |x| x == &guid)
);
named!(pub parse_guid<GUID>,
do_parse!(
d1: le_u32 >>
d2: le_u16 >>
d3: le_u16 >>
d4: le_u64 >>
(GUID(d1,d2,d3,d4))
)
);
pub trait AlignedParser {
fn align<'a>(&self, input: &'a [u8], count: usize) -> IResult<&'a [u8],usize>;
fn inc(&self, by: usize);
fn le_u32<'a>(&self, input: &'a [u8]) -> IResult<&'a [u8],u32> {
let (_i, _o) = self.align(input, 4)?;
let (_i, x) = le_u32(_i)?;
self.inc(4);
Ok((_i, x))
}
fn le_i32<'a>(&self, input: &'a [u8]) -> IResult<&'a [u8],i32> {
let (_i, _o) = self.align(input, 4)?;
let (_i, x) = le_i32(_i)?;
self.inc(4);
Ok((_i, x))
}
fn le_u16<'a>(&self, input: &'a [u8]) -> IResult<&'a [u8],u16> {
let (_i, _o) = self.align(input, 2)?;
let (_i, x) = le_u16(_i)?;
self.inc(2);
Ok((_i, x))
}
fn le_i16<'a>(&self, input: &'a [u8]) -> IResult<&'a [u8],i16> {
let (_i, _o) = self.align(input, 2)?;
let (_i, x) = le_i16(_i)?;
self.inc(2);
Ok((_i, x))
}
fn le_u8<'a>(&self, input: &'a [u8]) -> IResult<&'a [u8],u8> {
let (_i, x) = le_u8(input)?;
self.inc(1);
Ok((_i, x))
}
fn bitfield32<'a, F,C>(&self, input: &'a [u8], func: F) -> IResult<&'a [u8], C>
where F: Fn(u32) -> Option<C> {
map_opt!(input, call_m!(self.le_u32), func)
}
fn bitfield16<'a, F,C>(&self, input: &'a [u8], func: F) -> IResult<&'a [u8], C>
where F: Fn(u16) -> Option<C> {
map_opt!(input, call_m!(self.le_u16), func)
}
fn bitfield8<'a, F,C>(&self, input: &'a [u8], func: F) -> IResult<&'a [u8], C>
where F: Fn(u8) -> Option<C> {
map_opt!(input, call_m!(self.le_u8), func)
}
}
impl AlignedParser for Cell<usize> {
fn align<'a>(&self, input: &'a [u8], align: usize) -> IResult<&'a [u8],usize> {
let p0 = self.get();
let p1 = p0 % align;
let p2 = if p1 == 0 { 0 } else { align - p1 };
let (rest, _pad) = take!(input, p2)?;
let p3 = p0 + p2;
self.set(p3);
Ok((rest, p3))
}
fn inc(&self, by: usize) {
let offset = self.get();
self.set(offset + by);
}
}