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
use std::convert::From;
use std::marker::PhantomData;
use field::*;
use parse::*;
#[derive(Clone)]
pub struct MessageIter<'a> {
data: &'a [u8]
}
impl<'a> MessageIter<'a> {
pub fn new(data: &'a [u8]) -> Self {
MessageIter {
data: data
}
}
pub fn tag<T: From<ParseValue<'a>>>(self, tag: u32) -> ByTag<'a, T> {
ByTag {
tag: tag,
inner: self,
items: PhantomData
}
}
}
impl<'a> From<ParseValue<'a>> for MessageIter<'a> {
fn from(value: ParseValue<'a>) -> MessageIter<'a> {
match value {
ParseValue::LengthDelimited(data) =>
MessageIter::new(data.as_ref()),
_ =>
panic!("Expected buffer to parse")
}
}
}
impl<'a> Iterator for MessageIter<'a> {
type Item = Field<'a>;
fn next(&mut self) -> Option<Self::Item> {
parse_field(self.data)
.map(|(field, rest)| {
self.data = rest;
field
})
.ok()
}
}
#[derive(Clone)]
pub struct ByTag<'a, T: 'a + From<ParseValue<'a>>> {
tag: u32,
inner: MessageIter<'a>,
items: PhantomData<&'a T>
}
impl<'a, T: 'a + From<ParseValue<'a>>> Iterator for ByTag<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
.and_then(|msg| {
if msg.tag == self.tag {
Some(From::from(msg.value))
} else {
self.next()
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nested_iter() {
let data = [0x1a, 0x03, 0x08, 0x96, 0x01];
let mut outer = MessageIter::new(&data);
assert_eq!(outer.next(), Some(Field {
tag: 3,
value: ParseValue::LengthDelimited(&[0x08, 0x96, 0x01][..])
}));
assert_eq!(outer.next(), None);
let data = [0x08, 0x96, 0x01];
let mut inner = MessageIter::new(&data);
let m = inner.next().unwrap();
assert_eq!(1, m.tag);
assert_eq!(150u32, From::from(m.value));
assert_eq!(inner.next(), None);
}
#[test]
fn by_tag() {
let data = [0x08, 0x96, 0x01];
let iter = MessageIter::new(&data);
let r: Vec<u32> = iter.tag(1)
.collect();
assert_eq!(vec![150u32], r);
}
#[test]
fn nested_by_tag() {
let data = [0x1a, 0x03, 0x08, 0x96, 0x01];
let iter = MessageIter::new(&data);
let c = iter.tag::<MessageIter>(3).nth(0).unwrap();
let a = c.tag::<u32>(1).nth(0);
assert_eq!(Some(150u32), a);
}
}