darfk.net - Thomas Payne - Rust Notes

Flipping an Option<Result<T, E>> to a Result<Option<T>, E>

I was writing a command line application which took a regex from a flag, the details aren't important. I knew that the valid states for this parameter were:

let pattern: Option<String> = Some("[a-z]".into());

let pattern: Result<Option<Regex>, regex::Error> = pattern
    .as_ref()
    .map_or(
        Ok(None),
        // The following line turns Result<T, E> into a Result<Option<T>, E>
        |pattern| Regex::new(&pattern).map(Some)
    );

Converting a std::time::SystemTime to a chrono::DateTime

fn system_time_to_chrono_time(st: SystemTime) -> Option<DateTime<Utc>> {
    st.duration_since(SystemTime::UNIX_EPOCH)
        .ok()
        .map(|dur| DateTime::<Utc>::from_timestamp_secs(dur.as_secs() as i64))
        .flatten()
}

Recursively search for files

Ignores symlinks

pub fn recurse_directories_for_files<P>(path: P) -> io::Result<Vec<std::fs::DirEntry>>
where
    P: AsRef<std::path::Path>,
{
    let mut ret = Vec::<_>::new();

    let entries = fs::read_dir(path)?
        .into_iter()
        .collect::<io::Result<Vec<_>>>()?;

    for entry in entries {
        let metadata = entry.metadata()?;

        if metadata.is_symlink() {
            continue;
        }

        if metadata.is_dir() {
            ret.append(&mut recurse_directories_for_files(entry.path())?);
        } else if metadata.is_file() {
            ret.push(entry);
        }
    }

    Ok(ret)
}