]> git.lizzy.rs Git - rust.git/blob - src/test/ui/issues/issue-20797.rs
Auto merge of #78066 - bugadani:wat, r=jonas-schievink
[rust.git] / src / test / ui / issues / issue-20797.rs
1 // build-pass
2 // ignore-cloudabi no std::fs
3
4 // Regression test for #20797.
5
6 use std::default::Default;
7 use std::io;
8 use std::fs;
9 use std::path::PathBuf;
10
11 pub trait PathExtensions {
12     fn is_dir(&self) -> bool { false }
13 }
14
15 impl PathExtensions for PathBuf {}
16
17 /// A strategy for acquiring more subpaths to walk.
18 pub trait Strategy {
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;
25 }
26
27 /// The basic fully-recursive strategy. Nothing is pruned.
28 #[derive(Copy, Clone, Default)]
29 pub struct Recursive;
30
31 impl Strategy for Recursive {
32     type P = PathBuf;
33     fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
34         Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
35     }
36
37     fn prune(&self, _: &PathBuf) -> bool { false }
38 }
39
40 /// A directory walker of `P` using strategy `S`.
41 pub struct Subpaths<S: Strategy> {
42     stack: Vec<S::P>,
43     strategy: S,
44 }
45
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 })
51     }
52 }
53
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())
58     }
59 }
60
61 impl<S: Default + Strategy> Default for Subpaths<S> {
62     fn default() -> Subpaths<S> {
63         Subpaths { stack: Vec::new(), strategy: Default::default() }
64     }
65 }
66
67 impl<S: Strategy> Iterator for Subpaths<S> {
68     type Item = S::P;
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();
73         }
74         match opt_path {
75             Some(path) => {
76                 if path.is_dir() {
77                     let result = self.strategy.get_more(&path);
78                     match result {
79                         Ok(dirs) => { self.stack.extend(dirs); },
80                         Err(..) => { }
81                     }
82                 }
83                 Some(path)
84             }
85             None => None,
86         }
87     }
88 }
89
90 fn _foo() {
91     let _walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::from("/home")).unwrap();
92 }
93
94 fn main() {}