use imap_codec::types::{ core::{Tag, Text}, response::{Code as ImapCode, Status as ImapStatus}, }; use super::body::Body; use crate::errors::{Error, Result}; #[derive(Debug)] pub struct Response { pub(crate) status: Status, pub(crate) body: Option, } impl Response { pub fn status(code: StatusCode, msg: &str) -> Result { Ok(Response { status: Status::new(code, msg)?, body: None, }) } pub fn ok(msg: &str) -> Result { Self::status(StatusCode::Ok, msg) } pub fn no(msg: &str) -> Result { Self::status(StatusCode::No, msg) } pub fn bad(msg: &str) -> Result { Self::status(StatusCode::Bad, msg) } pub fn bye(msg: &str) -> Result { Self::status(StatusCode::Bye, msg) } } impl Response { pub fn with_extra_code(mut self, extra: ImapCode) -> Self { self.status.extra = Some(extra); self } pub fn with_body(mut self, body: impl Into) -> Self { self.body = Some(body.into()); self } } #[derive(Debug, Clone)] pub struct Status { pub(crate) code: StatusCode, pub(crate) extra: Option, pub(crate) text: Text, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum StatusCode { Ok, No, Bad, PreAuth, Bye, } impl Status { fn new(code: StatusCode, msg: &str) -> Result { Ok(Status { code, extra: None, text: msg.try_into().map_err(Error::text)?, }) } pub(crate) fn into_imap(self, tag: Option) -> ImapStatus { match self.code { StatusCode::Ok => ImapStatus::Ok { tag, code: self.extra, text: self.text, }, StatusCode::No => ImapStatus::No { tag, code: self.extra, text: self.text, }, StatusCode::Bad => ImapStatus::Bad { tag, code: self.extra, text: self.text, }, StatusCode::PreAuth => ImapStatus::PreAuth { code: self.extra, text: self.text, }, StatusCode::Bye => ImapStatus::Bye { code: self.extra, text: self.text, }, } } }