don't parse mail body until it's requested
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>embed
parent
4119a4285d
commit
a07f92a8a4
|
@ -29,5 +29,5 @@ optional = false
|
||||||
version = "5.86.0"
|
version = "5.86.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
#lto = true
|
||||||
#debug = true
|
debug = true
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
extern crate melib;
|
extern crate melib;
|
||||||
|
|
||||||
use melib::mailbox::email::Mail;
|
use melib::mailbox::email::Mail;
|
||||||
|
use melib::mailbox::backends::BackendOpGenerator;
|
||||||
|
use melib::mailbox::backends::maildir::MaildirOp;
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
use self::test::Bencher;
|
use self::test::Bencher;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn mail_parse(b: &mut Bencher) {
|
fn mail_parse(b: &mut Bencher) {
|
||||||
b.iter(|| Mail::from("test/attachment_test") );
|
b.iter(|| Mail::from(Box::new(BackendOpGenerator::new(Box::new(move || {
|
||||||
|
Box::new(MaildirOp::new("test/attachment_test".to_string()))})))) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
use mailbox::email::Mail;
|
use mailbox::email::Mail;
|
||||||
use error::{MeliError, Result};
|
use error::{MeliError, Result};
|
||||||
use mailbox::backends::{MailBackend, BackendOp, BackendOpGenerator};
|
use mailbox::backends::{MailBackend, BackendOp, BackendOpGenerator};
|
||||||
|
use mailbox::email::parser;
|
||||||
|
|
||||||
extern crate crossbeam;
|
extern crate crossbeam;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -48,7 +49,7 @@ impl Clone for MaildirOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaildirOp {
|
impl MaildirOp {
|
||||||
fn new(path: String) -> Self {
|
pub fn new(path: String) -> Self {
|
||||||
MaildirOp {
|
MaildirOp {
|
||||||
path: path,
|
path: path,
|
||||||
slice: None,
|
slice: None,
|
||||||
|
@ -66,7 +67,6 @@ impl BackendOp for MaildirOp {
|
||||||
}
|
}
|
||||||
Ok(unsafe { self.slice.as_ref().unwrap().as_slice() })
|
Ok(unsafe { self.slice.as_ref().unwrap().as_slice() })
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
fn fetch_headers(&mut self) -> Result<&[u8]> {
|
fn fetch_headers(&mut self) -> Result<&[u8]> {
|
||||||
let raw = self.as_bytes()?;
|
let raw = self.as_bytes()?;
|
||||||
let result = parser::headers_raw(raw).to_full_result()?;
|
let result = parser::headers_raw(raw).to_full_result()?;
|
||||||
|
@ -76,7 +76,7 @@ impl BackendOp for MaildirOp {
|
||||||
let raw = self.as_bytes()?;
|
let raw = self.as_bytes()?;
|
||||||
let result = parser::headers_raw(raw).to_full_result()?;
|
let result = parser::headers_raw(raw).to_full_result()?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]>;
|
fn as_bytes(&mut self) -> Result<&[u8]>;
|
||||||
//fn delete(&self) -> ();
|
//fn delete(&self) -> ();
|
||||||
//fn copy(&self
|
//fn copy(&self
|
||||||
//fn fetch_headers(&mut self) -> Result<&[u8]>;
|
fn fetch_headers(&mut self) -> Result<&[u8]>;
|
||||||
//fn fetch_body(&mut self) -> Result<&[u8]>;
|
fn fetch_body(&mut self) -> Result<&[u8]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BackendOpGenerator is a wrapper for a closure that returns a BackendOp object */
|
/* BackendOpGenerator is a wrapper for a closure that returns a BackendOp object */
|
||||||
|
|
|
@ -108,6 +108,7 @@ pub struct Mail
|
||||||
references: Option<References>,
|
references: Option<References>,
|
||||||
|
|
||||||
datetime: Option<chrono::DateTime<chrono::FixedOffset>>,
|
datetime: Option<chrono::DateTime<chrono::FixedOffset>>,
|
||||||
|
timestamp: i64,
|
||||||
thread: usize,
|
thread: usize,
|
||||||
|
|
||||||
operation_token: Arc<Box<BackendOpGenerator>>,
|
operation_token: Arc<Box<BackendOpGenerator>>,
|
||||||
|
@ -117,10 +118,7 @@ pub struct Mail
|
||||||
impl Mail
|
impl Mail
|
||||||
{
|
{
|
||||||
pub fn get_date(&self) -> i64 {
|
pub fn get_date(&self) -> i64 {
|
||||||
match self.datetime {
|
self.timestamp
|
||||||
Some(v) => v.timestamp(),
|
|
||||||
None => 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn get_datetime(&self) -> chrono::DateTime<chrono::FixedOffset> {
|
pub fn get_datetime(&self) -> chrono::DateTime<chrono::FixedOffset> {
|
||||||
self.datetime.unwrap_or_else(|| { chrono::FixedOffset::west(0).ymd(1970, 1, 1).and_hms(0, 0, 0)})
|
self.datetime.unwrap_or_else(|| { chrono::FixedOffset::west(0).ymd(1970, 1, 1).and_hms(0, 0, 0)})
|
||||||
|
@ -140,8 +138,29 @@ impl Mail
|
||||||
None => "",
|
None => "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_body(&self) -> &Attachment {
|
pub fn get_body(&self) -> Attachment {
|
||||||
self.body.as_ref().unwrap()
|
let mut operation = self.operation_token.generate();
|
||||||
|
let file = operation.as_bytes();
|
||||||
|
let (headers, body) = match parser::mail(file.unwrap()).to_full_result() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
let operation = self.operation_token.generate();
|
||||||
|
eprintln!("error in parsing mail\n{}", operation.description());
|
||||||
|
panic!();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let mut builder = AttachmentBuilder::new(body);
|
||||||
|
for (name, value) in headers {
|
||||||
|
if value.len() == 1 && value.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if name.eq_ignore_ascii_case("content-transfer-encoding") {
|
||||||
|
builder.content_transfer_encoding(value);
|
||||||
|
} else if name.eq_ignore_ascii_case("content-type") {
|
||||||
|
builder.content_type(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.build()
|
||||||
}
|
}
|
||||||
pub fn get_subject(&self) -> &str {
|
pub fn get_subject(&self) -> &str {
|
||||||
match self.subject {
|
match self.subject {
|
||||||
|
@ -253,6 +272,12 @@ impl Mail
|
||||||
}
|
}
|
||||||
pub fn set_datetime(&mut self, new_val: Option<chrono::DateTime<chrono::FixedOffset>>) -> () {
|
pub fn set_datetime(&mut self, new_val: Option<chrono::DateTime<chrono::FixedOffset>>) -> () {
|
||||||
self.datetime = new_val;
|
self.datetime = new_val;
|
||||||
|
if let Some(v) = self.datetime {
|
||||||
|
self.timestamp = v.timestamp();
|
||||||
|
if self.timestamp == 1485962960 {
|
||||||
|
eprintln!("it's {:?}", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn new(token: Box<BackendOpGenerator>) -> Self {
|
pub fn new(token: Box<BackendOpGenerator>) -> Self {
|
||||||
Mail {
|
Mail {
|
||||||
|
@ -266,6 +291,7 @@ impl Mail
|
||||||
references: None,
|
references: None,
|
||||||
|
|
||||||
datetime: None,
|
datetime: None,
|
||||||
|
timestamp: 0,
|
||||||
|
|
||||||
thread: 0,
|
thread: 0,
|
||||||
|
|
||||||
|
@ -275,23 +301,21 @@ impl Mail
|
||||||
}
|
}
|
||||||
pub fn from(operation_token: Box<BackendOpGenerator>) -> Option<Mail> {
|
pub fn from(operation_token: Box<BackendOpGenerator>) -> Option<Mail> {
|
||||||
let mut operation = operation_token.generate();
|
let mut operation = operation_token.generate();
|
||||||
let file = operation.as_bytes();
|
let headers = match parser::headers(operation.fetch_headers().unwrap()).to_full_result() {
|
||||||
if file.is_err() {
|
Ok(v) => {
|
||||||
return None;
|
v
|
||||||
}
|
},
|
||||||
let (headers, body) = match parser::mail(file.unwrap()).to_full_result() {
|
_ => {
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => {
|
|
||||||
let operation = operation_token.generate();
|
let operation = operation_token.generate();
|
||||||
eprintln!("error in parsing mail\n{}", operation.description());
|
eprintln!("error in parsing mail\n{}", operation.description());
|
||||||
return None;
|
return None;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mail = Mail::new(operation_token);
|
let mut mail = Mail::new(operation_token);
|
||||||
let mut in_reply_to = None;
|
let mut in_reply_to = None;
|
||||||
let mut datetime = None;
|
let mut datetime = None;
|
||||||
|
|
||||||
let mut builder = AttachmentBuilder::new(body);
|
|
||||||
for (name, value) in headers {
|
for (name, value) in headers {
|
||||||
if value.len() == 1 && value.is_empty() {
|
if value.len() == 1 && value.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -325,14 +349,11 @@ impl Mail
|
||||||
} else if name.eq_ignore_ascii_case("references") {
|
} else if name.eq_ignore_ascii_case("references") {
|
||||||
{
|
{
|
||||||
let parse_result = parser::references(value.as_bytes());
|
let parse_result = parser::references(value.as_bytes());
|
||||||
eprintln!("{:?}", value);
|
|
||||||
if parse_result.is_done() {
|
if parse_result.is_done() {
|
||||||
for v in parse_result.to_full_result().unwrap() {
|
for v in parse_result.to_full_result().unwrap() {
|
||||||
eprintln!("pushing {:?}", v);
|
|
||||||
mail.push_references(v);
|
mail.push_references(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eprintln!("\n\n");
|
|
||||||
}
|
}
|
||||||
mail.set_references(value.to_string());
|
mail.set_references(value.to_string());
|
||||||
} else if name.eq_ignore_ascii_case("in-reply-to") {
|
} else if name.eq_ignore_ascii_case("in-reply-to") {
|
||||||
|
@ -341,16 +362,11 @@ impl Mail
|
||||||
} else if name.eq_ignore_ascii_case("date") {
|
} else if name.eq_ignore_ascii_case("date") {
|
||||||
mail.set_date(value.to_string());
|
mail.set_date(value.to_string());
|
||||||
datetime = Some(value.to_string());
|
datetime = Some(value.to_string());
|
||||||
} else if name.eq_ignore_ascii_case("content-transfer-encoding") {
|
|
||||||
builder.content_transfer_encoding(value);
|
|
||||||
} else if name.eq_ignore_ascii_case("content-type") {
|
|
||||||
builder.content_type(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref mut x) = in_reply_to {
|
if let Some(ref mut x) = in_reply_to {
|
||||||
mail.push_references(x);
|
mail.push_references(x);
|
||||||
}
|
}
|
||||||
mail.set_body(builder.build());
|
|
||||||
if let Some(ref mut d) = datetime {
|
if let Some(ref mut d) = datetime {
|
||||||
mail.set_datetime(parser::date(d));
|
mail.set_datetime(parser::date(d));
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ named!(name<&str>,
|
||||||
named!(header<(&str, &str)>,
|
named!(header<(&str, &str)>,
|
||||||
separated_pair!(complete!(name), ws!(tag!(":")), complete!(header_value)));
|
separated_pair!(complete!(name), ws!(tag!(":")), complete!(header_value)));
|
||||||
/* Parse all headers -> Vec<(&str, Vec<&str>)> */
|
/* Parse all headers -> Vec<(&str, Vec<&str>)> */
|
||||||
named!(headers<std::vec::Vec<(&str, &str)>>,
|
named!(pub headers<std::vec::Vec<(&str, &str)>>,
|
||||||
many1!(complete!(header)));
|
many1!(complete!(header)));
|
||||||
|
|
||||||
named!(pub headers_raw<&[u8]>,
|
named!(pub headers_raw<&[u8]>,
|
||||||
|
|
Loading…
Reference in New Issue