imap_client/tasks/tasks/
search.rs1use 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}