imap_proto/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#[macro_use]
extern crate nom;
#[cfg(test)]
#[macro_use]
extern crate assert_matches;
#[macro_use]
mod macros;
pub mod body;
pub mod body_structure;
pub mod builders;
pub mod core;
mod parser;
pub mod types;
pub use crate::parser::{parse_response, resp_metadata, ParseResult};
pub use crate::types::*;
use std::borrow::Cow;
// Returns an escaped string if necessary for use as a "quoted" string per
// the IMAPv4 RFC. Return value does not include surrounding quote characters.
// Will return Err if the argument contains illegal characters.
//
// Relevant definitions from RFC 3501 formal syntax:
//
// string = quoted / literal [literal elided here]
// quoted = DQUOTE *QUOTED-CHAR DQUOTE
// QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials
// quoted-specials = DQUOTE / "\"
// TEXT-CHAR = <any CHAR except CR and LF>
fn quoted_string(s: &str) -> Result<Cow<str>, &'static str> {
let bytes = s.as_bytes();
let (mut start, mut new) = (0, Vec::<u8>::new());
for (i, b) in bytes.iter().enumerate() {
match *b {
b'\r' | b'\n' => {
return Err("CR and LF not allowed in quoted strings");
}
b'\\' | b'"' => {
if start < i {
new.extend(&bytes[start..i]);
}
new.push(b'\\');
new.push(*b);
start = i + 1;
}
_ => {}
};
}
if start == 0 {
Ok(Cow::Borrowed(s))
} else {
if start < bytes.len() {
new.extend(&bytes[start..]);
}
// Since the argument is a str, it must contain valid UTF-8. Since
// this function's transformation preserves the UTF-8 validity,
// unwrapping here should be okay.
Ok(Cow::Owned(String::from_utf8(new).unwrap()))
}
}
#[cfg(test)]
mod tests {
use super::quoted_string;
#[test]
fn test_quoted_string() {
assert_eq!(quoted_string("a").unwrap(), "a");
assert_eq!(quoted_string("").unwrap(), "");
assert_eq!(quoted_string("a\"b\\c").unwrap(), "a\\\"b\\\\c");
assert_eq!(quoted_string("\"foo\\").unwrap(), "\\\"foo\\\\");
assert!(quoted_string("\n").is_err());
}
}