Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/walkdir.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/walk.rs')
-rw-r--r--src/walk.rs339
1 files changed, 339 insertions, 0 deletions
diff --git a/src/walk.rs b/src/walk.rs
new file mode 100644
index 0000000..019f118
--- /dev/null
+++ b/src/walk.rs
@@ -0,0 +1,339 @@
+use std::cmp;
+use std::fmt;
+use std::path::{Path, PathBuf};
+use std::result;
+use std::usize;
+
+use crate::dent::DirEntry;
+use crate::error::Result;
+
+struct WalkDirOptions {
+ follow_links: bool,
+ max_open: usize,
+ min_depth: usize,
+ max_depth: usize,
+ sorter: Option<
+ Box<
+ FnMut(&DirEntry, &DirEntry) -> cmp::Ordering
+ + Send
+ + Sync
+ + 'static,
+ >,
+ >,
+ contents_first: bool,
+ same_file_system: bool,
+}
+
+impl fmt::Debug for WalkDirOptions {
+ fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+ let sorter_str = if self.sorter.is_some() {
+ // FnMut isn't `Debug`
+ "Some(...)"
+ } else {
+ "None"
+ };
+ f.debug_struct("WalkDirOptions")
+ .field("follow_links", &self.follow_links)
+ .field("max_open", &self.max_open)
+ .field("min_depth", &self.min_depth)
+ .field("max_depth", &self.max_depth)
+ .field("sorter", &sorter_str)
+ .field("contents_first", &self.contents_first)
+ .field("same_file_system", &self.same_file_system)
+ .finish()
+ }
+}
+
+/// TODO
+#[derive(Debug)]
+pub struct WalkDir {
+ root: PathBuf,
+ opts: WalkDirOptions,
+}
+
+impl IntoIterator for WalkDir {
+ type Item = Result<DirEntry>;
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> IntoIter {
+ unimplemented!()
+ }
+}
+
+impl WalkDir {
+ /// Create a builder for a recursive directory iterator starting at the
+ /// file path `root`. If `root` is a directory, then it is the first item
+ /// yielded by the iterator. If `root` is a file, then it is the first
+ /// and only item yielded by the iterator. If `root` is a symlink, then it
+ /// is always followed for the purposes of directory traversal. (A root
+ /// `DirEntry` still obeys its documentation with respect to symlinks and
+ /// the `follow_links` setting.)
+ pub fn new<P: Into<PathBuf>>(root: P) -> WalkDir {
+ WalkDir {
+ root: root.into(),
+ opts: WalkDirOptions {
+ follow_links: false,
+ max_open: 10,
+ min_depth: 0,
+ max_depth: usize::MAX,
+ sorter: None,
+ contents_first: false,
+ same_file_system: false,
+ },
+ }
+ }
+
+ /// Set the minimum depth of entries yielded by the iterator.
+ ///
+ /// The smallest depth is `0` and always corresponds to the path given
+ /// to the `new` function on this type. Its direct descendents have depth
+ /// `1`, and their descendents have depth `2`, and so on.
+ pub fn min_depth(mut self, depth: usize) -> WalkDir {
+ self.opts.min_depth = depth;
+ if self.opts.min_depth > self.opts.max_depth {
+ self.opts.min_depth = self.opts.max_depth;
+ }
+ self
+ }
+
+ /// Set the maximum depth of entries yield by the iterator.
+ ///
+ /// The smallest depth is `0` and always corresponds to the path given
+ /// to the `new` function on this type. Its direct descendents have depth
+ /// `1`, and their descendents have depth `2`, and so on.
+ ///
+ /// Note that this will not simply filter the entries of the iterator, but
+ /// it will actually avoid descending into directories when the depth is
+ /// exceeded.
+ pub fn max_depth(mut self, depth: usize) -> WalkDir {
+ self.opts.max_depth = depth;
+ if self.opts.max_depth < self.opts.min_depth {
+ self.opts.max_depth = self.opts.min_depth;
+ }
+ self
+ }
+
+ /// Follow symbolic links. By default, this is disabled.
+ ///
+ /// When `yes` is `true`, symbolic links are followed as if they were
+ /// normal directories and files. If a symbolic link is broken or is
+ /// involved in a loop, an error is yielded.
+ ///
+ /// When enabled, the yielded [`DirEntry`] values represent the target of
+ /// the link while the path corresponds to the link. See the [`DirEntry`]
+ /// type for more details.
+ ///
+ /// [`DirEntry`]: struct.DirEntry.html
+ pub fn follow_links(mut self, yes: bool) -> WalkDir {
+ self.opts.follow_links = yes;
+ self
+ }
+
+ /// Set the maximum number of simultaneously open file descriptors used
+ /// by the iterator.
+ ///
+ /// `n` must be greater than or equal to `1`. If `n` is `0`, then it is set
+ /// to `1` automatically. If this is not set, then it defaults to some
+ /// reasonably low number.
+ ///
+ /// This setting has no impact on the results yielded by the iterator
+ /// (even when `n` is `1`). Instead, this setting represents a trade off
+ /// between scarce resources (file descriptors) and memory. Namely, when
+ /// the maximum number of file descriptors is reached and a new directory
+ /// needs to be opened to continue iteration, then a previous directory
+ /// handle is closed and has its unyielded entries stored in memory. In
+ /// practice, this is a satisfying trade off because it scales with respect
+ /// to the *depth* of your file tree. Therefore, low values (even `1`) are
+ /// acceptable.
+ ///
+ /// Note that this value does not impact the number of system calls made by
+ /// an exhausted iterator.
+ ///
+ /// # Platform behavior
+ ///
+ /// On Windows, if `follow_links` is enabled, then this limit is not
+ /// respected. In particular, the maximum number of file descriptors opened
+ /// is proportional to the depth of the directory tree traversed.
+ pub fn max_open(mut self, mut n: usize) -> WalkDir {
+ if n == 0 {
+ n = 1;
+ }
+ self.opts.max_open = n;
+ self
+ }
+
+ /// Set a function for sorting directory entries.
+ ///
+ /// If a compare function is set, the resulting iterator will return all
+ /// paths in sorted order. The compare function will be called to compare
+ /// entries from the same directory.
+ ///
+ /// ```rust,no-run
+ /// use std::cmp;
+ /// use std::ffi::OsString;
+ /// use walkdir::WalkDir;
+ ///
+ /// WalkDir::new("foo").sort_by(|a,b| a.file_name().cmp(b.file_name()));
+ /// ```
+ pub fn sort_by<F>(mut self, cmp: F) -> WalkDir
+ where
+ F: FnMut(&DirEntry, &DirEntry) -> cmp::Ordering
+ + Send
+ + Sync
+ + 'static,
+ {
+ self.opts.sorter = Some(Box::new(cmp));
+ self
+ }
+
+ /// Yield a directory's contents before the directory itself. By default,
+ /// this is disabled.
+ ///
+ /// When `yes` is `false` (as is the default), the directory is yielded
+ /// before its contents are read. This is useful when, e.g. you want to
+ /// skip processing of some directories.
+ ///
+ /// When `yes` is `true`, the iterator yields the contents of a directory
+ /// before yielding the directory itself. This is useful when, e.g. you
+ /// want to recursively delete a directory.
+ ///
+ /// # Example
+ ///
+ /// Assume the following directory tree:
+ ///
+ /// ```text
+ /// foo/
+ /// abc/
+ /// qrs
+ /// tuv
+ /// def/
+ /// ```
+ ///
+ /// With contents_first disabled (the default), the following code visits
+ /// the directory tree in depth-first order:
+ ///
+ /// ```no_run
+ /// use walkdir::WalkDir;
+ ///
+ /// for entry in WalkDir::new("foo") {
+ /// let entry = entry.unwrap();
+ /// println!("{}", entry.path().display());
+ /// }
+ ///
+ /// // foo
+ /// // foo/abc
+ /// // foo/abc/qrs
+ /// // foo/abc/tuv
+ /// // foo/def
+ /// ```
+ ///
+ /// With contents_first enabled:
+ ///
+ /// ```no_run
+ /// use walkdir::WalkDir;
+ ///
+ /// for entry in WalkDir::new("foo").contents_first(true) {
+ /// let entry = entry.unwrap();
+ /// println!("{}", entry.path().display());
+ /// }
+ ///
+ /// // foo/abc/qrs
+ /// // foo/abc/tuv
+ /// // foo/abc
+ /// // foo/def
+ /// // foo
+ /// ```
+ pub fn contents_first(mut self, yes: bool) -> WalkDir {
+ self.opts.contents_first = yes;
+ self
+ }
+
+ /// Do not cross file system boundaries.
+ ///
+ /// When this option is enabled, directory traversal will not descend into
+ /// directories that are on a different file system from the root path.
+ ///
+ /// Currently, this option is only supported on Unix and Windows. If this
+ /// option is used on an unsupported platform, then directory traversal
+ /// will immediately return an error and will not yield any entries.
+ pub fn same_file_system(mut self, yes: bool) -> WalkDir {
+ self.opts.same_file_system = yes;
+ self
+ }
+}
+
+#[derive(Debug)]
+struct Walker {
+ root: PathBuf,
+ depth: usize,
+ opts: WalkDirOptions,
+}
+
+impl Walker {
+ fn new() -> Walker {
+ Walker {
+ root: PathBuf::new(),
+ depth: 0,
+ opts: WalkDirOptions {
+ follow_links: false,
+ max_open: 10,
+ min_depth: 0,
+ max_depth: usize::MAX,
+ sorter: None,
+ contents_first: false,
+ same_file_system: false,
+ },
+ }
+ }
+}
+
+/// TODO
+#[derive(Debug)]
+pub struct IntoIter {}
+
+impl Iterator for IntoIter {
+ type Item = Result<DirEntry>;
+
+ fn next(&mut self) -> Option<Result<DirEntry>> {
+ unimplemented!()
+ }
+}
+
+impl IntoIter {
+ /// TODO
+ pub fn filter_entry<P>(self, predicate: P) -> FilterEntry<Self, P>
+ where
+ P: FnMut(&DirEntry) -> bool,
+ {
+ FilterEntry { it: self, predicate: predicate }
+ }
+
+ /// TODO
+ pub fn skip_current_dir(&mut self) {
+ unimplemented!()
+ }
+}
+
+/// TODO
+#[derive(Debug)]
+pub struct FilterEntry<I, P> {
+ it: I,
+ predicate: P,
+}
+
+impl<P> Iterator for FilterEntry<IntoIter, P>
+where
+ P: FnMut(&DirEntry) -> bool,
+{
+ type Item = Result<DirEntry>;
+
+ /// Advances the iterator and returns the next value.
+ ///
+ /// # Errors
+ ///
+ /// If the iterator fails to retrieve the next value, this method returns
+ /// an error value. The error will be wrapped in an `Option::Some`.
+ fn next(&mut self) -> Option<Result<DirEntry>> {
+ unimplemented!()
+ }
+}