imap_proto/parser/
bodystructure.rs

1use std::collections::HashMap;
2
3use crate::types::BodyStructure;
4/// An utility parser helping to find the appropriate
5/// section part from a FETCH response.
6pub struct BodyStructParser<'a> {
7    root: &'a BodyStructure<'a>,
8    prefix: Vec<u32>,
9    iter: u32,
10    map: HashMap<Vec<u32>, &'a BodyStructure<'a>>,
11}
12
13impl<'a> BodyStructParser<'a> {
14    /// Returns a new parser
15    ///
16    /// # Arguments
17    ///
18    /// * `root` - The root of the `BodyStructure response.
19    pub fn new(root: &'a BodyStructure<'a>) -> Self {
20        let mut parser = BodyStructParser {
21            root,
22            prefix: vec![],
23            iter: 1,
24            map: HashMap::new(),
25        };
26
27        parser.parse(parser.root);
28        parser
29    }
30
31    /// Search particular element within the bodystructure.
32    ///
33    /// # Arguments
34    ///
35    /// * `func` - The filter used to search elements within the bodystructure.
36    pub fn search<F>(&self, func: F) -> Option<Vec<u32>>
37    where
38        F: Fn(&'a BodyStructure<'a>) -> bool,
39    {
40        let elem: Vec<_> = self
41            .map
42            .iter()
43            .filter_map(|(k, v)| {
44                if func(v) {
45                    let slice: &[u32] = k;
46                    Some(slice)
47                } else {
48                    None
49                }
50            })
51            .collect();
52        elem.first().map(|a| a.to_vec())
53    }
54
55    /// Reetr
56    fn parse(&mut self, node: &'a BodyStructure) {
57        match node {
58            BodyStructure::Multipart { bodies, .. } => {
59                let vec = self.prefix.clone();
60                self.map.insert(vec, node);
61
62                for (i, n) in bodies.iter().enumerate() {
63                    self.iter += i as u32;
64                    self.prefix.push(self.iter);
65                    self.parse(n);
66                    self.prefix.pop();
67                }
68                self.iter = 1;
69            }
70            _ => {
71                let vec = self.prefix.clone();
72                self.map.insert(vec, node);
73            }
74        };
75    }
76}