3 // Regression test for #20797.
5 use std
::default::Default
;
8 use std
::path
::PathBuf
;
10 pub trait PathExtensions
{
11 fn is_dir(&self) -> bool { false }
14 impl PathExtensions
for PathBuf {}
16 /// A strategy for acquiring more subpaths to walk.
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
;
26 /// The basic fully-recursive strategy. Nothing is pruned.
27 #[derive(Copy, Clone, Default)]
30 impl Strategy
for Recursive
{
32 fn get_more(&self, p
: &PathBuf
) -> io
::Result
<Vec
<PathBuf
>> {
33 Ok(fs
::read_dir(p
).unwrap().map(|s
| s
.unwrap().path()).collect())
36 fn prune(&self, _
: &PathBuf
) -> bool { false }
39 /// A directory walker of `P` using strategy `S`.
40 pub struct Subpaths
<S
: Strategy
> {
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 }
)
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())
60 impl<S
: Default
+ Strategy
> Default
for Subpaths
<S
> {
61 fn default() -> Subpaths
<S
> {
62 Subpaths { stack: Vec::new(), strategy: Default::default() }
66 impl<S
: Strategy
> Iterator
for Subpaths
<S
> {
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();
76 let result
= self.strategy
.get_more(&path
);
78 Ok(dirs
) => { self.stack.extend(dirs); }
,
90 let _walker
: Subpaths
<Recursive
> = Subpaths
::walk(&PathBuf
::from("/home")).unwrap();