pop3_codec/types/
response.rs

1use std::fmt::Debug;
2
3#[cfg(feature = "serdex")]
4use serde::{Deserialize, Serialize};
5
6// -- Greeting --
7
8#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Greeting {
11    /// An empty vector is used for "no code"
12    pub code: Vec<String>,
13    pub comment: String,
14    pub timestamp: Option<String>,
15}
16
17#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct SingleLine {
20    /// An empty vector is used for "no code"
21    pub code: Vec<String>,
22    pub comment: String,
23}
24
25#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct MultiLine<T>
28where
29    // TODO: relax trait bound
30    T: Debug + Clone + PartialEq + Eq,
31{
32    pub head: SingleLine,
33    pub body: Vec<T>,
34}
35
36#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub enum Response<O, E>
39where
40    // TODO: relax trait bounds
41    O: Debug + Clone + PartialEq + Eq,
42    E: Debug + Clone + PartialEq + Eq,
43{
44    Ok(O),
45    Err(E),
46}
47
48impl<O, E> Response<O, E>
49where
50    // TODO: relax trait bound
51    O: Debug + Clone + PartialEq + Eq,
52    E: Debug + Clone + PartialEq + Eq,
53{
54    pub fn unwrap(self) -> O {
55        match self {
56            Response::Ok(o) => o,
57            Response::Err(e) => panic!("{:?}", e),
58        }
59    }
60}
61
62#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub struct DropListing {
65    pub message_count: u32,
66    pub maildrop_size: u32,
67}
68
69#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
70#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct ScanListing {
72    pub message_id: u32,
73    pub message_size: u32,
74}
75
76#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct UniqueIdListing {
79    pub message_id: u32,
80    pub message_uid: String,
81}
82
83#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct LanguageListing {
86    pub tag: String, // TODO: see RFC5646
87    pub description: String,
88}
89
90#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub enum Capability {
93    // -- RFC2449 --
94    Top,
95    User,
96    Sasl {
97        mechanisms: Vec<String>, // TODO: String --> Mechanism
98    },
99    RespCodes,
100    LoginDelay {
101        minimum_seconds: u32,
102        per_user: bool,
103    },
104    Pipelining,
105    Expire {
106        policy: ExpirePolicy,
107        per_user: bool,
108    },
109    Uidl,
110    Implementation {
111        text: String,
112    },
113    // -- RFC2595 --
114    Stls,
115    // -- RFC3206 --
116    AuthRespCode,
117    // -- RFC6856 --
118    Utf8 {
119        in_credentials: bool,
120    },
121    Lang,
122    // -----------------------
123    Other {
124        tag: String,
125        parameters: Vec<String>,
126    },
127}
128
129impl ToString for Capability {
130    fn to_string(&self) -> String {
131        use Capability::*;
132
133        match self {
134            Top => "TOP".into(),
135            User => "USER".into(),
136            Sasl { mechanisms } => {
137                format!("SASL {}", mechanisms.join(" "))
138            }
139            RespCodes => "RESP-CODES".into(),
140            LoginDelay {
141                minimum_seconds,
142                per_user,
143            } => {
144                let mut out = format!("LOGIN-DELAY {}", minimum_seconds);
145                if *per_user {
146                    out.push_str(" USER");
147                }
148                out
149            }
150            Pipelining => "PIPELINING".into(),
151            Expire { policy, per_user } => {
152                let mut out = format!("EXPIRE {}", policy.to_string());
153                if *per_user {
154                    out.push_str(" USER");
155                }
156                out
157            }
158            Uidl => "UIDL".into(),
159            Implementation { text: tag } => format!("IMPLEMENTATION {}", tag),
160            Stls => "STLS".into(),
161            AuthRespCode => "AUTH-RESP-CODE".into(),
162            Utf8 { in_credentials } => {
163                if *in_credentials {
164                    "UTF8 USER".into()
165                } else {
166                    "UTF8".into()
167                }
168            }
169            Lang => "LANG".into(),
170            Other { tag, parameters } => format!("{} {}", tag, parameters.join(" ")),
171        }
172    }
173}
174
175#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub enum ExpirePolicy {
178    Never,
179    MinimumDays(u32),
180}
181
182impl ToString for ExpirePolicy {
183    fn to_string(&self) -> String {
184        match self {
185            ExpirePolicy::Never => "NEVER".into(),
186            ExpirePolicy::MinimumDays(days) => days.to_string(),
187        }
188    }
189}