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
        }
    }
}

/// Recursive for LengthDelimited
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()
    }
}

/// Returned by MessageIter.tag()
#[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);
    }
}