2 // ignore-cloudabi no std::fs
4 // Regression test for #20797.
6 use std::default::Default;
9 use std::path::PathBuf;
11 pub trait PathExtensions {
12 fn is_dir(&self) -> bool { false }
15 impl PathExtensions for PathBuf {}
17 /// A strategy for acquiring more subpaths to walk.
19 type P: PathExtensions;
20 /// Gets additional subpaths from a given path.
21 fn get_more(&self, item: &Self::P) -> io::Result<Vec<Self::P>>;
22 /// Determine whether a path should be walked further.
23 /// This is run against each item from `get_more()`.
24 fn prune(&self, p: &Self::P) -> bool;
27 /// The basic fully-recursive strategy. Nothing is pruned.
28 #[derive(Copy, Clone, Default)]
31 impl Strategy for Recursive {
33 fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
34 Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
37 fn prune(&self, _: &PathBuf) -> bool { false }
40 /// A directory walker of `P` using strategy `S`.
41 pub struct Subpaths<S: Strategy> {
46 impl<S: Strategy> Subpaths<S> {
47 /// Creates a directory walker with a root path and strategy.
48 pub fn new(p: &S::P, strategy: S) -> io::Result<Subpaths<S>> {
49 let stack = strategy.get_more(p)?;
50 Ok(Subpaths { stack: stack, strategy: strategy })
54 impl<S: Default + Strategy> Subpaths<S> {
55 /// Creates a directory walker with a root path and a default strategy.
56 pub fn walk(p: &S::P) -> io::Result<Subpaths<S>> {
57 Subpaths::new(p, Default::default())
61 impl<S: Default + Strategy> Default for Subpaths<S> {
62 fn default() -> Subpaths<S> {
63 Subpaths { stack: Vec::new(), strategy: Default::default() }
67 impl<S: Strategy> Iterator for Subpaths<S> {
69 fn next (&mut self) -> Option<S::P> {
70 let mut opt_path = self.stack.pop();
71 while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
72 opt_path = self.stack.pop();
77 let result = self.strategy.get_more(&path);
79 Ok(dirs) => { self.stack.extend(dirs); },
91 let _walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::from("/home")).unwrap();