]> git.lizzy.rs Git - rust.git/blob - src/test/ui/issues/issue-20797.rs
Rollup merge of #86479 - exphp-forks:float-debug-exponential, r=yaahc
[rust.git] / src / test / ui / issues / issue-20797.rs
1 // build-pass
2
3 // Regression test for #20797.
4
5 use std::default::Default;
6 use std::io;
7 use std::fs;
8 use std::path::PathBuf;
9
10 pub trait PathExtensions {
11     fn is_dir(&self) -> bool { false }
12 }
13
14 impl PathExtensions for PathBuf {}
15
16 /// A strategy for acquiring more subpaths to walk.
17 pub trait Strategy {
18     type P: PathExtensions;
19     /// Gets additional subpaths from a given path.
20     fn get_more(&self, item: &Self::P) -> io::Result<Vec<Self::P>>;
21     /// Determine whether a path should be walked further.
22     /// This is run against each item from `get_more()`.
23     fn prune(&self, p: &Self::P) -> bool;
24 }
25
26 /// The basic fully-recursive strategy. Nothing is pruned.
27 #[derive(Copy, Clone, Default)]
28 pub struct Recursive;
29
30 impl Strategy for Recursive {
31     type P = PathBuf;
32     fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
33         Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
34     }
35
36     fn prune(&self, _: &PathBuf) -> bool { false }
37 }
38
39 /// A directory walker of `P` using strategy `S`.
40 pub struct Subpaths<S: Strategy> {
41     stack: Vec<S::P>,
42     strategy: S,
43 }
44
45 impl<S: Strategy> Subpaths<S> {
46     /// Creates a directory walker with a root path and strategy.
47     pub fn new(p: &S::P, strategy: S) -> io::Result<Subpaths<S>> {
48         let stack = strategy.get_more(p)?;
49         Ok(Subpaths { stack: stack, strategy: strategy })
50     }
51 }
52
53 impl<S: Default + Strategy> Subpaths<S> {
54     /// Creates a directory walker with a root path and a default strategy.
55     pub fn walk(p: &S::P) -> io::Result<Subpaths<S>> {
56         Subpaths::new(p, Default::default())
57     }
58 }
59
60 impl<S: Default + Strategy> Default for Subpaths<S> {
61     fn default() -> Subpaths<S> {
62         Subpaths { stack: Vec::new(), strategy: Default::default() }
63     }
64 }
65
66 impl<S: Strategy> Iterator for Subpaths<S> {
67     type Item = S::P;
68     fn next (&mut self) -> Option<S::P> {
69         let mut opt_path = self.stack.pop();
70         while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
71             opt_path = self.stack.pop();
72         }
73         match opt_path {
74             Some(path) => {
75                 if path.is_dir() {
76                     let result = self.strategy.get_more(&path);
77                     match result {
78                         Ok(dirs) => { self.stack.extend(dirs); },
79                         Err(..) => { }
80                     }
81                 }
82                 Some(path)
83             }
84             None => None,
85         }
86     }
87 }
88
89 fn _foo() {
90     let _walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::from("/home")).unwrap();
91 }
92
93 fn main() {}