]> git.lizzy.rs Git - rust.git/blob - src/test/ui/issues/issue-20797.rs
Auto merge of #54624 - arielb1:evaluate-outlives, r=nikomatsakis
[rust.git] / src / test / ui / issues / issue-20797.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // compile-pass
12 // ignore-cloudabi no std::fs
13
14 // Regression test for #20797.
15
16 use std::default::Default;
17 use std::io;
18 use std::fs;
19 use std::path::PathBuf;
20
21 pub trait PathExtensions {
22     fn is_dir(&self) -> bool { false }
23 }
24
25 impl PathExtensions for PathBuf {}
26
27 /// A strategy for acquiring more subpaths to walk.
28 pub trait Strategy {
29     type P: PathExtensions;
30     /// Get additional subpaths from a given path.
31     fn get_more(&self, item: &Self::P) -> io::Result<Vec<Self::P>>;
32     /// Determine whether a path should be walked further.
33     /// This is run against each item from `get_more()`.
34     fn prune(&self, p: &Self::P) -> bool;
35 }
36
37 /// The basic fully-recursive strategy. Nothing is pruned.
38 #[derive(Copy, Clone, Default)]
39 pub struct Recursive;
40
41 impl Strategy for Recursive {
42     type P = PathBuf;
43     fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
44         Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
45     }
46
47     fn prune(&self, _: &PathBuf) -> bool { false }
48 }
49
50 /// A directory walker of `P` using strategy `S`.
51 pub struct Subpaths<S: Strategy> {
52     stack: Vec<S::P>,
53     strategy: S,
54 }
55
56 impl<S: Strategy> Subpaths<S> {
57     /// Create a directory walker with a root path and strategy.
58     pub fn new(p: &S::P, strategy: S) -> io::Result<Subpaths<S>> {
59         let stack = strategy.get_more(p)?;
60         Ok(Subpaths { stack: stack, strategy: strategy })
61     }
62 }
63
64 impl<S: Default + Strategy> Subpaths<S> {
65     /// Create a directory walker with a root path and a default strategy.
66     pub fn walk(p: &S::P) -> io::Result<Subpaths<S>> {
67         Subpaths::new(p, Default::default())
68     }
69 }
70
71 impl<S: Default + Strategy> Default for Subpaths<S> {
72     fn default() -> Subpaths<S> {
73         Subpaths { stack: Vec::new(), strategy: Default::default() }
74     }
75 }
76
77 impl<S: Strategy> Iterator for Subpaths<S> {
78     type Item = S::P;
79     fn next (&mut self) -> Option<S::P> {
80         let mut opt_path = self.stack.pop();
81         while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
82             opt_path = self.stack.pop();
83         }
84         match opt_path {
85             Some(path) => {
86                 if path.is_dir() {
87                     let result = self.strategy.get_more(&path);
88                     match result {
89                         Ok(dirs) => { self.stack.extend(dirs); },
90                         Err(..) => { }
91                     }
92                 }
93                 Some(path)
94             }
95             None => None,
96         }
97     }
98 }
99
100 fn _foo() {
101     let _walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::from("/home")).unwrap();
102 }
103
104 fn main() {}