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
//! Provides `Fragments` iterator for splitting a data slice into fragment slices, whose
//! size depends on the data packet used.
//!
//! A data message is made up of unlimited data fragments, with the FSNF field of the
//! packet header determining how the message is reconstructed from the fragments.

use std;

use data::params::*;

/// Fragments for confirmed data packets.
pub type ConfirmedFragments<'a> = Fragments<'a, ConfirmedParams>;

/// Fragments for unconfirmed data packets.
pub type UnconfirmedFragments<'a> = Fragments<'a, UnconfirmedParams>;

/// Iterator over data fragments, yielding fragment-sized data slices to be turned into
/// payload blocks.
pub struct Fragments<'a, P: PacketParams> {
    params: std::marker::PhantomData<P>,
    /// data to be split.
    data: &'a [u8],
    /// Current byte index into `data`.
    pos: usize,
}

impl<'a, P: PacketParams> Fragments<'a, P> {
    /// Construct a new `Fragments` over the given data.
    pub fn new(data: &'a [u8]) -> Fragments<'a, P> {
        Fragments {
            params: std::marker::PhantomData,
            data: data,
            pos: 0,
        }
    }
}

impl<'a, P: PacketParams> Iterator for Fragments<'a, P> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<Self::Item> {
        if self.pos >= self.data.len() {
            return None;
        }

        let start = self.pos;
        let stop = std::cmp::min(start + P::packet_bytes(), self.data.len());

        self.pos = stop;

        Some(&self.data[start..stop])
    }
}

#[cfg(test)]
mod test {
    use super::Fragments;
    use data::params::*;

    #[test]
    fn test_fragments() {
        struct TestParams;

        impl PacketParams for TestParams {
            fn packet_bytes() -> usize { 2 }
            fn block_bytes() -> usize{ 0 }
            fn tail_bytes() -> usize { 0 }
        }

        let bytes = [1];
        let mut f = Fragments::<TestParams>::new(&bytes);
        assert_eq!(f.next().unwrap(), &[1]);
        assert!(f.next().is_none());

        let bytes = [1, 2, 3, 4];
        let mut f = Fragments::<TestParams>::new(&bytes);
        assert_eq!(f.next().unwrap(), &[1, 2]);
        assert_eq!(f.next().unwrap(), &[3, 4]);
        assert!(f.next().is_none());

        let bytes = [1, 2, 3, 4, 5];
        let mut f = Fragments::<TestParams>::new(&bytes);
        assert_eq!(f.next().unwrap(), &[1, 2]);
        assert_eq!(f.next().unwrap(), &[3, 4]);
        assert_eq!(f.next().unwrap(), &[5]);
        assert!(f.next().is_none());
    }
}