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
//! Performs path normalization for *nix and Windows systems.
//!
//! Windows and Unix-like systems handle glob patterns completely differently.
//! This library is meant to paper over the differences between the two in order
//! to simplify the construction of cross-platform applications.

use glob::Paths;
use std::io;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub enum PathIter {
    Directory(walkdir::IntoIter),
    File(Option<PathBuf>),
    Glob(Paths),
}

impl Iterator for PathIter {
    type Item = io::Result<PathBuf>;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            PathIter::Directory(dir) => {
                let next = dir.next()?;
                Some(next.map(|x| x.into_path()).map_err(|e| e.into()))
            }
            PathIter::File(path) => path.take().map(Ok),
            PathIter::Glob(paths) => {
                let next = paths.next()?;
                Some(
                    next.map(|x| x.as_path().into())
                        .map_err(|e| io::Error::new(io::ErrorKind::Other, e)),
                )
            }
        }
    }
}

pub fn extract_paths(path: &str) -> io::Result<PathIter> {
    {
        let path: &Path = path.as_ref();

        // Not a glob
        if path.exists() {
            if path.is_file() {
                return Ok(PathIter::File(Some(path.into())));
            } else {
                let iter = WalkDir::new(path).into_iter();
                return Ok(PathIter::Directory(iter));
            }
        }
    }

    glob::glob(path)
        .map(PathIter::Glob)
        .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
}