~kmaasrud/maildirpp

9555943f32fe16fc40b3f0bd39d970fbc72cb582 — Knut Magnus Aasrud 5 months ago cae18d9
perf: improve performance slightly
2 files changed, 31 insertions(+), 35 deletions(-)

M src/entry.rs
M src/lib.rs
M src/entry.rs => src/entry.rs +22 -23
@@ 34,25 34,20 @@ impl MailEntry {
                .as_bytes(),
        )?;

        let mut split = filename.split(SEP).peekable();
        let mut id = split.next().unwrap().to_string();
        while let Some(s) = split.next() {
            if split.peek().is_some() {
                id.push_str(s);
            }
        }

        let flags = filename
            .split(&format!("{SEP}2,")) // We are ignoring any experimental info (marked `:1,`)
            .last() // Allow the occurence of `:2,` in the filename
            .unwrap_or("")
            .chars()
            .map(TryFrom::try_from)
            .filter_map(Result::ok)
            .collect();
        let (id, flags) = match filename.rsplit_once(SEP) {
            Some((id, flags)) => (
                id,
                flags
                    .chars()
                    .map(TryFrom::try_from)
                    .filter_map(Result::ok)
                    .collect(),
            ),
            None => (filename, HashSet::new()),
        };

        Ok(MailEntry {
            id,
            id: id.to_string(),
            flags,
            path: path.to_path_buf(),
        })


@@ 74,7 69,7 @@ impl MailEntry {

    fn update(&mut self) -> Result<(), Error> {
        let new_file_name = format!(
            "{id}{SEP}2,{flags}",
            "{id}{SEP}{flags}",
            id = self.id,
            flags = self.flags_to_string()
        );


@@ 82,12 77,16 @@ impl MailEntry {
        let prev_path = self.path.clone();
        let new_path = self.path.with_file_name(new_file_name);

        if new_path.exists() {
            return Err(Error::AlreadyExistsError(new_path));
        match fs::rename(prev_path, &self.path) {
            Ok(_) => {
                self.path = new_path;
                Ok(())
            }
            Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {
                Err(Error::AlreadyExistsError(new_path))
            }
            Err(e) => Err(e.into()),
        }

        self.path = new_path;
        Ok(fs::rename(prev_path, &self.path)?)
    }

    /// Get the unique identifier of the email message.

M src/lib.rs => src/lib.rs +9 -12
@@ 25,9 25,9 @@ const CUR: &str = "cur";
const NEW: &str = "new";
const TMP: &str = "tmp";
#[cfg(unix)]
const SEP: &str = ":";
const SEP: &str = ":2,";
#[cfg(windows)]
const SEP: &str = ";";
const SEP: &str = ";2,";

static COUNTER: AtomicUsize = AtomicUsize::new(0);



@@ 66,9 66,7 @@ impl Maildir {
    /// Ensures that the necessary subfolders exist.
    fn ensure_dirs(&self) -> Result<(), Error> {
        for dir in &[&self.cur, &self.new, &self.tmp] {
            if !dir.exists() {
                fs::create_dir_all(dir)?;
            }
            fs::create_dir_all(dir)?;
        }
        Ok(())
    }


@@ 77,8 75,9 @@ impl Maildir {
    pub fn clean_tmp(&self) -> Result<(), Error> {
        for entry in fs::read_dir(&self.tmp)? {
            let path = entry?.path();
            let metadata = path.metadata()?;
            // If the file is older than 36 hours, delete it
            if path.is_file() && path.metadata()?.modified()?.elapsed()?.as_secs() > 36 * 60 * 60 {
            if metadata.is_file() && metadata.modified()?.elapsed()?.as_secs() > 36 * 60 * 60 {
                fs::remove_file(path)?;
            }
        }


@@ 289,12 288,10 @@ impl Maildir {
            }
        }

        /// At this point, `file` is our new file at `tmppath`. If we
        /// leave the scope of this function prior to
        /// successfully writing the file to its final
        /// location, we need to ensure that we remove
        /// the temporary file. This struct takes care
        /// of that detail.
        /// At this point, `file` is our new file at `tmppath`. If we leave the
        /// scope of this function prior to successfully writing the file to its
        /// final location, we need to ensure that we remove the temporary file.
        /// This struct takes care of that detail.
        struct RemoveOnDrop {
            path_to_remove: PathBuf,
        }