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.
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.
11 // Regression test for #20797.
13 // pretty-expanded FIXME #23616
15 #![feature(question_mark)]
17 use std
::default::Default
;
20 use std
::path
::PathBuf
;
22 pub trait PathExtensions
{
23 fn is_dir(&self) -> bool { false }
26 impl PathExtensions
for PathBuf {}
28 /// A strategy for acquiring more subpaths to walk.
30 type P
: PathExtensions
;
31 /// Get additional subpaths from a given path.
32 fn get_more(&self, item
: &Self::P
) -> io
::Result
<Vec
<Self::P
>>;
33 /// Determine whether a path should be walked further.
34 /// This is run against each item from `get_more()`.
35 fn prune(&self, p
: &Self::P
) -> bool
;
38 /// The basic fully-recursive strategy. Nothing is pruned.
39 #[derive(Copy, Clone, Default)]
42 impl Strategy
for Recursive
{
44 fn get_more(&self, p
: &PathBuf
) -> io
::Result
<Vec
<PathBuf
>> {
45 Ok(fs
::read_dir(p
).unwrap().map(|s
| s
.unwrap().path()).collect())
48 fn prune(&self, _
: &PathBuf
) -> bool { false }
51 /// A directory walker of `P` using strategy `S`.
52 pub struct Subpaths
<S
: Strategy
> {
57 impl<S
: Strategy
> Subpaths
<S
> {
58 /// Create a directory walker with a root path and strategy.
59 pub fn new(p
: &S
::P
, strategy
: S
) -> io
::Result
<Subpaths
<S
>> {
60 let stack
= strategy
.get_more(p
)?
;
61 Ok(Subpaths { stack: stack, strategy: strategy }
)
65 impl<S
: Default
+ Strategy
> Subpaths
<S
> {
66 /// Create a directory walker with a root path and a default strategy.
67 pub fn walk(p
: &S
::P
) -> io
::Result
<Subpaths
<S
>> {
68 Subpaths
::new(p
, Default
::default())
72 impl<S
: Default
+ Strategy
> Default
for Subpaths
<S
> {
73 fn default() -> Subpaths
<S
> {
74 Subpaths { stack: Vec::new(), strategy: Default::default() }
78 impl<S
: Strategy
> Iterator
for Subpaths
<S
> {
80 fn next (&mut self) -> Option
<S
::P
> {
81 let mut opt_path
= self.stack
.pop();
82 while opt_path
.is_some() && self.strategy
.prune(opt_path
.as_ref().unwrap()) {
83 opt_path
= self.stack
.pop();
88 let result
= self.strategy
.get_more(&path
);
90 Ok(dirs
) => { self.stack.extend(dirs); }
,
102 let _walker
: Subpaths
<Recursive
> = Subpaths
::walk(&PathBuf
::from("/home")).unwrap();