imap_client/tasks/tasks/
search.rs

1use std::num::NonZeroU32;
2
3use imap_next::imap_types::{
4    command::CommandBody,
5    core::Vec1,
6    response::{Data, StatusBody, StatusKind},
7    search::SearchKey,
8};
9
10use super::TaskError;
11use crate::tasks::Task;
12
13#[derive(Clone, Debug)]
14pub struct SearchTask {
15    criteria: Vec1<SearchKey<'static>>,
16    uid: bool,
17    output: Vec<NonZeroU32>,
18}
19
20impl SearchTask {
21    pub fn new(criteria: Vec1<SearchKey<'static>>) -> Self {
22        Self {
23            criteria,
24            ..Default::default()
25        }
26    }
27
28    pub fn set_uid(&mut self, uid: bool) {
29        self.uid = uid;
30    }
31
32    pub fn with_uid(mut self, uid: bool) -> Self {
33        self.set_uid(uid);
34        self
35    }
36}
37
38impl Default for SearchTask {
39    fn default() -> Self {
40        Self {
41            criteria: Vec1::from(SearchKey::All),
42            uid: true,
43            output: Default::default(),
44        }
45    }
46}
47
48impl Task for SearchTask {
49    type Output = Result<Vec<NonZeroU32>, TaskError>;
50
51    fn command_body(&self) -> CommandBody<'static> {
52        CommandBody::Search {
53            charset: None,
54            criteria: self.criteria.clone(),
55            uid: self.uid,
56        }
57    }
58
59    fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
60        if let Data::Search(ids) = data {
61            self.output = ids;
62            None
63        } else {
64            Some(data)
65        }
66    }
67
68    fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
69        match status_body.kind {
70            StatusKind::Ok => Ok(self.output),
71            StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
72            StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
73        }
74    }
75}