pass unsolicited responses channel by reference

as suggested in
https://github.com/mattnenterprise/rust-imap/pull/91#issuecomment-434055085
This commit is contained in:
Johannes Schilling 2018-10-29 23:10:09 +01:00
parent f98398aecf
commit 930bd86dbf
2 changed files with 34 additions and 34 deletions

View file

@ -469,13 +469,13 @@ impl<T: Read + Write> Session<T> {
/// `unsolicited_responses` channel of the [`Session`](struct.Session.html). /// `unsolicited_responses` channel of the [`Session`](struct.Session.html).
pub fn select(&mut self, mailbox_name: &str) -> Result<Mailbox> { pub fn select(&mut self, mailbox_name: &str) -> Result<Mailbox> {
self.run_command_and_read_response(&format!("SELECT {}", validate_str(mailbox_name)?)) self.run_command_and_read_response(&format!("SELECT {}", validate_str(mailbox_name)?))
.and_then(|lines| parse_mailbox(&lines[..], self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx))
} }
/// Examine is identical to Select, but the selected mailbox is identified as read-only /// Examine is identical to Select, but the selected mailbox is identified as read-only
pub fn examine(&mut self, mailbox_name: &str) -> Result<Mailbox> { pub fn examine(&mut self, mailbox_name: &str) -> Result<Mailbox> {
self.run_command_and_read_response(&format!("EXAMINE {}", validate_str(mailbox_name)?)) self.run_command_and_read_response(&format!("EXAMINE {}", validate_str(mailbox_name)?))
.and_then(|lines| parse_mailbox(&lines[..], self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx))
} }
/// Fetch retreives data associated with a set of messages in the mailbox. /// Fetch retreives data associated with a set of messages in the mailbox.
@ -485,7 +485,7 @@ impl<T: Read + Write> Session<T> {
/// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7). /// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7).
pub fn fetch(&mut self, sequence_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> { pub fn fetch(&mut self, sequence_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
self.run_command_and_read_response(&format!("FETCH {} {}", sequence_set, query)) self.run_command_and_read_response(&format!("FETCH {} {}", sequence_set, query))
.and_then(|lines| parse_fetches(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_fetches(lines, &mut self.unsolicited_responses_tx))
} }
/// Fetch retreives data associated with a set of messages by UID in the mailbox. /// Fetch retreives data associated with a set of messages by UID in the mailbox.
@ -495,7 +495,7 @@ impl<T: Read + Write> Session<T> {
/// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7). /// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7).
pub fn uid_fetch(&mut self, uid_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> { pub fn uid_fetch(&mut self, uid_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
self.run_command_and_read_response(&format!("UID FETCH {} {}", uid_set, query)) self.run_command_and_read_response(&format!("UID FETCH {} {}", uid_set, query))
.and_then(|lines| parse_fetches(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_fetches(lines, &mut self.unsolicited_responses_tx))
} }
/// Noop always succeeds, and it does nothing. /// Noop always succeeds, and it does nothing.
@ -542,7 +542,7 @@ impl<T: Read + Write> Session<T> {
/// Capability requests a listing of capabilities that the server supports. /// Capability requests a listing of capabilities that the server supports.
pub fn capabilities(&mut self) -> ZeroCopyResult<Capabilities> { pub fn capabilities(&mut self) -> ZeroCopyResult<Capabilities> {
self.run_command_and_read_response("CAPABILITY") self.run_command_and_read_response("CAPABILITY")
.and_then(|lines| parse_capabilities(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_capabilities(lines, &mut self.unsolicited_responses_tx))
} }
/// Expunge permanently removes all messages that have the \Deleted flag set from the currently /// Expunge permanently removes all messages that have the \Deleted flag set from the currently
@ -572,12 +572,12 @@ impl<T: Read + Write> Session<T> {
/// Store alters data associated with a message in the mailbox. /// Store alters data associated with a message in the mailbox.
pub fn store(&mut self, sequence_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> { pub fn store(&mut self, sequence_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
self.run_command_and_read_response(&format!("STORE {} {}", sequence_set, query)) self.run_command_and_read_response(&format!("STORE {} {}", sequence_set, query))
.and_then(|lines| parse_fetches(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_fetches(lines, &mut self.unsolicited_responses_tx))
} }
pub fn uid_store(&mut self, uid_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> { pub fn uid_store(&mut self, uid_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
self.run_command_and_read_response(&format!("UID STORE {} {}", uid_set, query)) self.run_command_and_read_response(&format!("UID STORE {} {}", uid_set, query))
.and_then(|lines| parse_fetches(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_fetches(lines, &mut self.unsolicited_responses_tx))
} }
/// Copy copies the specified message to the end of the specified destination mailbox. /// Copy copies the specified message to the end of the specified destination mailbox.
@ -624,7 +624,7 @@ impl<T: Read + Write> Session<T> {
quote!(reference_name), quote!(reference_name),
mailbox_search_pattern mailbox_search_pattern
)) ))
.and_then(|lines| parse_names(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_names(lines, &mut self.unsolicited_responses_tx))
} }
/// The LSUB command returns a subset of names from the set of names /// The LSUB command returns a subset of names from the set of names
@ -639,7 +639,7 @@ impl<T: Read + Write> Session<T> {
quote!(reference_name), quote!(reference_name),
mailbox_search_pattern mailbox_search_pattern
)) ))
.and_then(|lines| parse_names(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_names(lines, &mut self.unsolicited_responses_tx))
} }
/// The STATUS command requests the status of the indicated mailbox. /// The STATUS command requests the status of the indicated mailbox.
@ -649,7 +649,7 @@ impl<T: Read + Write> Session<T> {
validate_str(mailbox_name)?, validate_str(mailbox_name)?,
status_data_items status_data_items
)) ))
.and_then(|lines| parse_mailbox(&lines[..], self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx))
} }
/// Returns a handle that can be used to block until the state of the currently selected /// Returns a handle that can be used to block until the state of the currently selected
@ -676,14 +676,14 @@ impl<T: Read + Write> Session<T> {
/// the list of message sequence numbers of those messages. /// the list of message sequence numbers of those messages.
pub fn search(&mut self, query: &str) -> Result<HashSet<u32>> { pub fn search(&mut self, query: &str) -> Result<HashSet<u32>> {
self.run_command_and_read_response(&format!("SEARCH {}", query)) self.run_command_and_read_response(&format!("SEARCH {}", query))
.and_then(|lines| parse_ids(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_ids(lines, &mut self.unsolicited_responses_tx))
} }
/// Searches the mailbox for messages that match the given criteria and returns /// Searches the mailbox for messages that match the given criteria and returns
/// the list of unique identifier numbers of those messages. /// the list of unique identifier numbers of those messages.
pub fn uid_search(&mut self, query: &str) -> Result<HashSet<u32>> { pub fn uid_search(&mut self, query: &str) -> Result<HashSet<u32>> {
self.run_command_and_read_response(&format!("UID SEARCH {}", query)) self.run_command_and_read_response(&format!("UID SEARCH {}", query))
.and_then(|lines| parse_ids(lines, self.unsolicited_responses_tx.clone())) .and_then(|lines| parse_ids(lines, &mut self.unsolicited_responses_tx))
} }
// these are only here because they are public interface, the rest is in `Connection` // these are only here because they are public interface, the rest is in `Connection`

View file

@ -24,7 +24,7 @@ enum MapOrNot<T> {
Ignore, Ignore,
} }
unsafe fn parse_many<T, F>(lines: Vec<u8>, mut map: F, unsolicited: mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<T>> unsafe fn parse_many<T, F>(lines: Vec<u8>, mut map: F, unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<T>>
where where
F: FnMut(Response<'static>) -> MapOrNot<T>, F: FnMut(Response<'static>) -> MapOrNot<T>,
{ {
@ -80,7 +80,7 @@ where
ZeroCopy::new(lines, f) ZeroCopy::new(lines, f)
} }
pub fn parse_names(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<Name>> { pub fn parse_names(lines: Vec<u8>, unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<Name>> {
use imap_proto::MailboxDatum; use imap_proto::MailboxDatum;
let f = |resp| match resp { let f = |resp| match resp {
// https://github.com/djc/imap-proto/issues/4 // https://github.com/djc/imap-proto/issues/4
@ -104,7 +104,7 @@ pub fn parse_names(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedResponse
unsafe { parse_many(lines, f, unsolicited) } unsafe { parse_many(lines, f, unsolicited) }
} }
pub fn parse_fetches(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<Fetch>> { pub fn parse_fetches(lines: Vec<u8>, unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Vec<Fetch>> {
let f = |resp| match resp { let f = |resp| match resp {
Response::Fetch(num, attrs) => { Response::Fetch(num, attrs) => {
let mut fetch = Fetch { let mut fetch = Fetch {
@ -138,7 +138,7 @@ pub fn parse_fetches(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedRespon
unsafe { parse_many(lines, f, unsolicited) } unsafe { parse_many(lines, f, unsolicited) }
} }
pub fn parse_capabilities(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Capabilities> { pub fn parse_capabilities(lines: Vec<u8>, unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> ZeroCopyResult<Capabilities> {
let f = |mut lines| { let f = |mut lines| {
let mut caps = HashSet::new(); let mut caps = HashSet::new();
loop { loop {
@ -168,7 +168,7 @@ pub fn parse_capabilities(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedR
unsafe { ZeroCopy::new(lines, f) } unsafe { ZeroCopy::new(lines, f) }
} }
pub fn parse_mailbox(mut lines: &[u8], unsolicited: mpsc::Sender<UnsolicitedResponse>) -> Result<Mailbox> { pub fn parse_mailbox(mut lines: &[u8], unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> Result<Mailbox> {
let mut mailbox = Mailbox::default(); let mut mailbox = Mailbox::default();
loop { loop {
@ -237,7 +237,7 @@ pub fn parse_mailbox(mut lines: &[u8], unsolicited: mpsc::Sender<UnsolicitedResp
} }
} }
pub fn parse_ids(lines: Vec<u8>, unsolicited: mpsc::Sender<UnsolicitedResponse>) -> Result<HashSet<u32>> { pub fn parse_ids(lines: Vec<u8>, unsolicited: &mut mpsc::Sender<UnsolicitedResponse>) -> Result<HashSet<u32>> {
let mut lines = &lines[..]; let mut lines = &lines[..];
let mut ids = HashSet::new(); let mut ids = HashSet::new();
loop { loop {
@ -272,8 +272,8 @@ mod tests {
fn parse_capability_test() { fn parse_capability_test() {
let expected_capabilities = vec!["IMAP4rev1", "STARTTLS", "AUTH=GSSAPI", "LOGINDISABLED"]; let expected_capabilities = vec!["IMAP4rev1", "STARTTLS", "AUTH=GSSAPI", "LOGINDISABLED"];
let lines = b"* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n"; let lines = b"* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let capabilities = parse_capabilities(lines.to_vec(), send).unwrap(); let capabilities = parse_capabilities(lines.to_vec(), &mut send).unwrap();
// shouldn't be any unexpected responses parsed // shouldn't be any unexpected responses parsed
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
assert_eq!(capabilities.len(), 4); assert_eq!(capabilities.len(), 4);
@ -285,17 +285,17 @@ mod tests {
#[test] #[test]
#[should_panic] #[should_panic]
fn parse_capability_invalid_test() { fn parse_capability_invalid_test() {
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let lines = b"* JUNK IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n"; let lines = b"* JUNK IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n";
parse_capabilities(lines.to_vec(), send).unwrap(); parse_capabilities(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
} }
#[test] #[test]
fn parse_names_test() { fn parse_names_test() {
let lines = b"* LIST (\\HasNoChildren) \".\" \"INBOX\"\r\n"; let lines = b"* LIST (\\HasNoChildren) \".\" \"INBOX\"\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let names = parse_names(lines.to_vec(), send).unwrap(); let names = parse_names(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
assert_eq!(names.len(), 1); assert_eq!(names.len(), 1);
assert_eq!(names[0].attributes(), &["\\HasNoChildren"]); assert_eq!(names[0].attributes(), &["\\HasNoChildren"]);
@ -306,8 +306,8 @@ mod tests {
#[test] #[test]
fn parse_fetches_empty() { fn parse_fetches_empty() {
let lines = b""; let lines = b"";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let fetches = parse_fetches(lines.to_vec(), send).unwrap(); let fetches = parse_fetches(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
assert!(fetches.is_empty()); assert!(fetches.is_empty());
} }
@ -317,8 +317,8 @@ mod tests {
let lines = b"\ let lines = b"\
* 24 FETCH (FLAGS (\\Seen) UID 4827943)\r\n\ * 24 FETCH (FLAGS (\\Seen) UID 4827943)\r\n\
* 25 FETCH (FLAGS (\\Seen))\r\n"; * 25 FETCH (FLAGS (\\Seen))\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let fetches = parse_fetches(lines.to_vec(), send).unwrap(); let fetches = parse_fetches(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
assert_eq!(fetches.len(), 2); assert_eq!(fetches.len(), 2);
assert_eq!(fetches[0].message, 24); assert_eq!(fetches[0].message, 24);
@ -337,8 +337,8 @@ mod tests {
let lines = b"\ let lines = b"\
* 37 FETCH (UID 74)\r\n\ * 37 FETCH (UID 74)\r\n\
* 1 RECENT\r\n"; * 1 RECENT\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let fetches = parse_fetches(lines.to_vec(), send).unwrap(); let fetches = parse_fetches(lines.to_vec(), &mut send).unwrap();
assert_eq!(recv.try_recv(), Ok(UnsolicitedResponse::Recent(1))); assert_eq!(recv.try_recv(), Ok(UnsolicitedResponse::Recent(1)));
assert_eq!(fetches.len(), 1); assert_eq!(fetches.len(), 1);
assert_eq!(fetches[0].message, 37); assert_eq!(fetches[0].message, 37);
@ -349,8 +349,8 @@ mod tests {
fn parse_ids_test() { fn parse_ids_test() {
let lines = b"* SEARCH 1600 1698 1739 1781 1795 1885 1891 1892 1893 1898 1899 1901 1911 1926 1932 1933 1993 1994 2007 2032 2033 2041 2053 2062 2063 2065 2066 2072 2078 2079 2082 2084 2095 2100 2101 2102 2103 2104 2107 2116 2120 2135 2138 2154 2163 2168 2172 2189 2193 2198 2199 2205 2212 2213 2221 2227 2267 2275 2276 2295 2300 2328 2330 2332 2333 2334\r\n\ let lines = b"* SEARCH 1600 1698 1739 1781 1795 1885 1891 1892 1893 1898 1899 1901 1911 1926 1932 1933 1993 1994 2007 2032 2033 2041 2053 2062 2063 2065 2066 2072 2078 2079 2082 2084 2095 2100 2101 2102 2103 2104 2107 2116 2120 2135 2138 2154 2163 2168 2172 2189 2193 2198 2199 2205 2212 2213 2221 2227 2267 2275 2276 2295 2300 2328 2330 2332 2333 2334\r\n\
* SEARCH 2335 2336 2337 2338 2339 2341 2342 2347 2349 2350 2358 2359 2362 2369 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2390 2392 2397 2400 2401 2403 2405 2409 2411 2414 2417 2419 2420 2424 2426 2428 2439 2454 2456 2467 2468 2469 2490 2515 2519 2520 2521\r\n"; * SEARCH 2335 2336 2337 2338 2339 2341 2342 2347 2349 2350 2358 2359 2362 2369 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2390 2392 2397 2400 2401 2403 2405 2409 2411 2414 2417 2419 2420 2424 2426 2428 2439 2454 2456 2467 2468 2469 2490 2515 2519 2520 2521\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let ids = parse_ids(lines.to_vec(), send).unwrap(); let ids = parse_ids(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
let ids: HashSet<u32> = ids.iter().cloned().collect(); let ids: HashSet<u32> = ids.iter().cloned().collect();
assert_eq!( assert_eq!(
@ -372,8 +372,8 @@ mod tests {
); );
let lines = b"* SEARCH\r\n"; let lines = b"* SEARCH\r\n";
let (send, recv) = mpsc::channel(); let (mut send, recv) = mpsc::channel();
let ids = parse_ids(lines.to_vec(), send).unwrap(); let ids = parse_ids(lines.to_vec(), &mut send).unwrap();
assert!(recv.try_recv().is_err()); assert!(recv.try_recv().is_err());
let ids: HashSet<u32> = ids.iter().cloned().collect(); let ids: HashSet<u32> = ids.iter().cloned().collect();
assert_eq!(ids, HashSet::<u32>::new()); assert_eq!(ids, HashSet::<u32>::new());