switch to owned responses instead of references

This commit is contained in:
Michael Zhang 2021-02-21 08:59:27 -06:00
parent a5dc3eebcb
commit 5db86a9a41
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
5 changed files with 136 additions and 24 deletions

View file

@ -19,12 +19,11 @@ use tokio_rustls::{
}; };
use crate::command::Command; use crate::command::Command;
use crate::types::Response; use crate::response::Response;
use super::ClientConfig; use super::ClientConfig;
pub type BoxedFunc = Box<dyn Fn()>; pub type ResultMap = Arc<RwLock<HashMap<usize, (Option<Response>, Option<Waker>)>>>;
pub type ResultMap = Arc<RwLock<HashMap<usize, (Option<String>, Option<Waker>)>>>;
pub type GreetingState = Arc<RwLock<(bool, Option<Waker>)>>; pub type GreetingState = Arc<RwLock<(bool, Option<Waker>)>>;
pub const TAG_PREFIX: &str = "panorama"; pub const TAG_PREFIX: &str = "panorama";
@ -85,7 +84,7 @@ where
} }
/// Sends a command to the server and returns a handle to retrieve the result /// Sends a command to the server and returns a handle to retrieve the result
pub async fn execute(&mut self, cmd: Command) -> Result<String> { pub async fn execute(&mut self, cmd: Command) -> Result<Response> {
debug!("executing command {:?}", cmd); debug!("executing command {:?}", cmd);
let id = self.id; let id = self.id;
self.id += 1; self.id += 1;
@ -116,13 +115,10 @@ where
.execute(cmd) .execute(cmd)
.await .await
.context("error executing CAPABILITY command")?; .context("error executing CAPABILITY command")?;
let (_, resp) = Response::from_bytes(result.as_bytes()) debug!("cap resp: {:?}", result);
.map_err(|err| anyhow!("")) // if let Response::Capabilities(caps) = resp {
.context("error parsing response from CAPABILITY")?; // debug!("capabilities: {:?}", caps);
debug!("cap resp: {:?}", resp); // }
if let Response::Capabilities(caps) = resp {
debug!("capabilities: {:?}", caps);
}
Ok(()) Ok(())
} }
@ -217,6 +213,9 @@ where
match future::select(fut, fut2).await { match future::select(fut, fut2).await {
Either::Left((_, _)) => { Either::Left((_, _)) => {
debug!("got a new line"); debug!("got a new line");
let (_, resp) = crate::parser::parse_response(next_line.as_bytes()).unwrap();
let resp = Response::from(resp);
debug!("parsed as: {:?}", resp);
let next_line = next_line.trim_end_matches('\n').trim_end_matches('\r'); let next_line = next_line.trim_end_matches('\n').trim_end_matches('\r');
let mut parts = next_line.split(" "); let mut parts = next_line.split(" ");
@ -241,7 +240,7 @@ where
let mut results = results.write(); let mut results = results.write();
if let Some((c, w)) = results.get_mut(&id) { if let Some((c, w)) = results.get_mut(&id) {
// *c = Some(rest.to_string()); // *c = Some(rest.to_string());
*c = Some(next_line.to_owned()); *c = Some(resp);
if let Some(waker) = w.take() { if let Some(waker) = w.take() {
waker.wake(); waker.wake();
} }

View file

@ -1,33 +1,141 @@
use std::str::FromStr; use std::ops::RangeInclusive;
use crate::types::{
AttributeValue as AttributeValue_, Capability as Capability_, MailboxDatum as MailboxDatum_,
RequestId, Response as Response_, ResponseCode as ResponseCode_, State, Status,
};
#[derive(Clone, Debug)]
pub enum Response { pub enum Response {
Capabilities(Vec<Capability>), Capabilities(Vec<Capability>),
Continue {
code: Option<ResponseCode>,
information: Option<String>,
},
Done { Done {
tag: RequestId, tag: RequestId,
status: Status, status: Status,
code: Option<ResponseCode>, code: Option<ResponseCode>,
information: Option<String>, information: Option<String>,
}, },
Data {
status: Status,
code: Option<ResponseCode>,
information: Option<String>,
},
Expunge(u32),
Vanished {
earlier: bool,
uids: Vec<RangeInclusive<u32>>,
},
Fetch(u32, Vec<AttributeValue>),
MailboxData(MailboxDatum),
} }
impl FromStr for Response { impl<'a> From<Response_<'a>> for Response {
type Err = anyhow::Error; fn from(b: Response_) -> Self {
fn from_str(s: &str) -> Result<Self, Self::Err> { use Response_::*;
todo!() match b {
Capabilities(caps) => {
Response::Capabilities(caps.into_iter().map(Capability::from).collect())
}
Continue { code, information } => Response::Continue {
code: code.map(ResponseCode::from),
information: information.map(str::to_owned),
},
Done {
tag,
status,
code,
information,
} => Response::Done {
tag,
status,
code: code.map(ResponseCode::from),
information: information.map(str::to_owned),
},
Data {
status,
code,
information,
} => Response::Data {
status,
code: code.map(ResponseCode::from),
information: information.map(str::to_owned),
},
Expunge(n) => Response::Expunge(n),
Vanished {earlier, uids} => Response::Vanished{earlier, uids},
_ => todo!("nyi: {:?}", b),
}
} }
} }
#[derive(Clone, Debug)]
pub enum Capability { pub enum Capability {
Imap4rev1, Imap4rev1,
Auth(String), Auth(String),
Atom(String), Atom(String),
} }
pub struct RequestId(pub String); impl<'a> From<Capability_<'a>> for Capability {
fn from(b: Capability_) -> Self {
pub enum Status { use Capability_::*;
Ok, match b {
No, Imap4rev1 => Capability::Imap4rev1,
Auth(s) => Capability::Auth(s.to_owned()),
Atom(s) => Capability::Atom(s.to_owned()),
}
}
} }
pub enum ResponseCode {} #[derive(Clone, Debug)]
pub enum ResponseCode {
Alert,
BadCharset(Option<Vec<String>>),
Capabilities(Vec<Capability>),
HighestModSeq(u64), // RFC 4551, section 3.1.1
Parse,
PermanentFlags(Vec<String>),
ReadOnly,
ReadWrite,
TryCreate,
UidNext(u32),
UidValidity(u32),
Unseen(u32),
AppendUid(u32, Vec<UidSetMember>),
CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
UidNotSticky,
}
impl<'a> From<ResponseCode_<'a>> for ResponseCode {
fn from(b: ResponseCode_) -> Self {
use ResponseCode_::*;
match b {
Alert => ResponseCode::Alert,
BadCharset(s) => {
ResponseCode::BadCharset(s.map(|v| v.into_iter().map(str::to_owned).collect()))
}
Capabilities(v) => {
ResponseCode::Capabilities(v.into_iter().map(Capability::from).collect())
}
HighestModSeq(n) => ResponseCode::HighestModSeq(n),
Parse => ResponseCode::Parse,
_ => todo!("nyi: {:?}", b),
}
}
}
#[derive(Clone, Debug)]
pub enum UidSetMember {
UidRange(RangeInclusive<u32>),
Uid(u32),
}
#[derive(Clone, Debug)]
pub enum AttributeValue {
}
#[derive(Clone, Debug)]
pub enum MailboxDatum {
}

View file

@ -44,7 +44,7 @@ impl<'a> Response<'a> {
} }
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum Status { pub enum Status {
Ok, Ok,
No, No,

View file

@ -89,5 +89,10 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
// debug!("sending CAPABILITY"); // debug!("sending CAPABILITY");
// let result = unauth.capabilities().await?; // let result = unauth.capabilities().await?;
loop {
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
debug!("heartbeat");
}
} }
} }