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
use std::collections::HashMap;

use crate::types::BodyStructure;
/// An utility parser helping to find the appropriate
/// section part from a FETCH response.
pub struct BodyStructParser<'a> {
    root: &'a BodyStructure<'a>,
    prefix: Vec<u32>,
    iter: u32,
    map: HashMap<Vec<u32>, &'a BodyStructure<'a>>,
}

impl<'a> BodyStructParser<'a> {
    /// Returns a new parser
    ///
    /// # Arguments
    ///
    /// * `root` - The root of the `BodyStructure response.
    pub fn new(root: &'a BodyStructure<'a>) -> Self {
        let mut parser = BodyStructParser {
            root,
            prefix: vec![],
            iter: 1,
            map: HashMap::new(),
        };

        parser.parse(parser.root);
        parser
    }

    /// Search particular element within the bodystructure.
    ///
    /// # Arguments
    ///
    /// * `func` - The filter used to search elements within the bodystructure.
    pub fn search<F>(&self, func: F) -> Option<Vec<u32>>
    where
        F: Fn(&'a BodyStructure<'a>) -> bool,
    {
        let elem: Vec<_> = self
            .map
            .iter()
            .filter_map(|(k, v)| {
                if func(v) {
                    let slice: &[u32] = k;
                    Some(slice)
                } else {
                    None
                }
            })
            .collect();
        elem.first().map(|a| a.to_vec())
    }

    /// Reetr
    fn parse(&mut self, node: &'a BodyStructure) {
        match node {
            BodyStructure::Multipart { bodies, .. } => {
                let vec = self.prefix.clone();
                self.map.insert(vec, node);

                for (i, n) in bodies.iter().enumerate() {
                    self.iter += i as u32;
                    self.prefix.push(self.iter);
                    self.parse(n);
                    self.prefix.pop();
                }
                self.iter = 1;
            }
            _ => {
                let vec = self.prefix.clone();
                self.map.insert(vec, node);
            }
        };
    }
}