dir_structure/
dir_descendants.rs

1//! A structure representing the descendants of a directory.
2//!
3//! See [`DirDescendants`] for more details.
4
5use core::fmt::Debug;
6use core::slice;
7use std::fmt;
8use std::marker;
9use std::ops;
10use std::ops::Deref;
11use std::ops::DerefMut;
12use std::path::Path;
13use std::pin::Pin;
14#[cfg(feature = "async")]
15use std::task::Context;
16#[cfg(feature = "async")]
17use std::task::Poll;
18use std::vec;
19
20#[cfg(feature = "async")]
21use futures::future::BoxFuture;
22#[cfg(feature = "async")]
23use pin_project::pin_project;
24
25use crate::NoFilter;
26use crate::error::VfsResult;
27use crate::prelude::*;
28#[cfg(feature = "async")]
29use crate::traits::async_vfs::WriteSupportingVfsAsync;
30#[cfg(feature = "resolve-path")]
31use crate::traits::resolve::DynamicHasField;
32use crate::traits::vfs;
33use crate::traits::vfs::DirEntryInfo;
34use crate::traits::vfs::DirWalker;
35use crate::traits::vfs::OwnedPathType;
36use crate::traits::vfs::PathType;
37#[cfg(feature = "async")]
38use crate::traits::vfs::VfsCore;
39
40/// A structure representing the descendants of a directory.
41///
42/// This is different from [`DirChildren`](crate::dir_children::DirChildren), as the descendants include all
43/// files and folders within the directory, not just the immediate children, as is the case with
44/// [`DirChildren`](crate::dir_children::DirChildren).
45///
46/// The `F` type parameter allows for custom filtering of the descendants, as follows:
47///
48/// - its [`FolderFilter`] implementation tells us whether to attempt to parse a specific folder as `T`, storing it into the result set.
49/// - its [`FolderRecurseFilter`] tells us whether to recurse into a specific folder, but not necessarily parse it as `T`.
50/// - its [`FileFilter`] implementation tells us whether to attempt to parse a specific file as `T`, storing it into the result set.
51///
52/// \* note that [`FolderFilter`] and [`FolderRecurseFilter`] may both allow the same path, in which case we will both recurse
53/// into the folder, and attempt to parse it as a `T`.
54#[derive(PartialEq)]
55#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
56pub struct DirDescendants<
57    T,
58    F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P> = NoFilter,
59    P: PathType + ?Sized = Path,
60> {
61    descendants: Vec<DirDescendant<T, P>>,
62    _phantom: marker::PhantomData<F>,
63}
64
65impl<T: Debug, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
66    Debug for DirDescendants<T, F, P>
67where
68    P::PathSegmentOwned: Debug,
69    P::OwnedPath: Debug,
70{
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        f.debug_struct("DirDescendants")
73            .field("descendants", &self.descendants)
74            .finish()
75    }
76}
77
78impl<T: Clone, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
79    Clone for DirDescendants<T, F, P>
80{
81    fn clone(&self) -> Self {
82        Self {
83            descendants: self.descendants.clone(),
84            _phantom: marker::PhantomData,
85        }
86    }
87}
88
89impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
90    DirDescendants<T, F, P>
91{
92    /// Create a new [`DirDescendants`] instance from a list of [`DirDescendant`]s.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
98    ///
99    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![]);
100    /// assert!(descendants.is_empty());
101    ///
102    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![
103    ///   DirDescendant::new("child1", "child1", "child1", ()),
104    ///   DirDescendant::new("child2", "child2", "child2", ()),
105    /// ]);
106    /// assert_eq!(descendants.len(), 2);
107    /// ```
108    pub fn new(descendants: Vec<DirDescendant<T, P>>) -> Self {
109        Self {
110            descendants,
111            _phantom: marker::PhantomData,
112        }
113    }
114
115    /// Returns the number of descendants.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
121    ///
122    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![]);
123    /// assert_eq!(descendants.len(), 0);
124    ///
125    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![
126    ///   DirDescendant::new("child1", "child1", "child1", ()),
127    ///   DirDescendant::new("child2", "child2", "child2", ()),
128    /// ]);
129    /// assert_eq!(descendants.len(), 2);
130    /// ```
131    pub fn len(&self) -> usize {
132        self.descendants.len()
133    }
134
135    /// Returns whether there are no descendants.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
141    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![]);
142    /// assert_eq!(descendants.is_empty(), true);
143    ///
144    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![
145    ///   DirDescendant::new("child1", "child1", "child1", ()),
146    ///   DirDescendant::new("child2", "child2", "child2", ()),
147    /// ]);
148    /// assert_eq!(descendants.is_empty(), false);
149    /// ```
150    pub fn is_empty(&self) -> bool {
151        self.descendants.is_empty()
152    }
153
154    /// Returns an iterator over the descendants.
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
160    ///
161    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![]);
162    /// let mut i = descendants.iter();
163    /// assert_eq!(i.next(), None);
164    ///
165    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![
166    ///     DirDescendant::new("child1", "child1", "child1", ()),
167    ///     DirDescendant::new("child2", "child2", "child2", ()),
168    /// ]);
169    /// let mut i = descendants.iter();
170    /// assert_eq!(i.next(), Some(&DirDescendant::new("child1", "child1", "child1", ())));
171    /// assert_eq!(i.next(), Some(&DirDescendant::new("child2", "child2", "child2", ())));
172    /// assert_eq!(i.next(), None);
173    /// ```
174    pub fn iter(&self) -> DirDescendantsIter<'_, T, P> {
175        DirDescendantsIter(self.descendants.iter())
176    }
177
178    /// Returns an iterator over the mutable descendants.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
184    ///
185    /// let mut descendants = DirDescendants::<(), NoFilter>::new(vec![]);
186    /// let mut i = descendants.iter_mut();
187    /// assert_eq!(i.next(), None);
188    ///
189    /// let mut descendants = DirDescendants::<(), NoFilter>::new(vec![
190    ///     DirDescendant::new("child1", "child1", "child1", ()),
191    ///     DirDescendant::new("child2", "child2", "child2", ()),
192    /// ]);
193    /// let mut i = descendants.iter_mut();
194    /// assert_eq!(i.next(), Some(&mut DirDescendant::new("child1", "child1", "child1", ())));
195    /// assert_eq!(i.next(), Some(&mut DirDescendant::new("child2", "child2", "child2", ())));
196    /// assert_eq!(i.next(), None);
197    /// ```
198    pub fn iter_mut(&mut self) -> DirDescendantsIterMut<'_, T, P> {
199        DirDescendantsIterMut(self.descendants.iter_mut())
200    }
201
202    /// Returns the descendant at the given index, or `None` if out of bounds.
203    ///
204    /// # Examples
205    ///
206    /// ```
207    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
208    ///
209    /// let descendants = DirDescendants::<(), NoFilter>::new(vec![
210    ///     DirDescendant::new("child1", "child1", "child1", ()),
211    ///     DirDescendant::new("child2", "child2", "child2", ()),
212    /// ]);
213    ///
214    /// assert_eq!(descendants.len(), 2);
215    /// assert_eq!(descendants.get(0), Some(&DirDescendant::new("child1", "child1", "child1", ())));
216    /// assert_eq!(descendants.get(1), Some(&DirDescendant::new("child2", "child2", "child2", ())));
217    /// assert_eq!(descendants.get(2), None);
218    /// assert_eq!(descendants.get(100), None);
219    /// ```
220    pub fn get(&self, index: usize) -> Option<&DirDescendant<T, P>> {
221        self.descendants.get(index)
222    }
223
224    /// Returns a mutable reference to the descendant at the given index, or `None` if out of bounds.
225    /// This is a mutable version of [`get`](Self::get).
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
231    ///
232    /// let mut descendants = DirDescendants::<(), NoFilter>::new(vec![
233    ///     DirDescendant::new("child1", "child1", "child1", ()),
234    ///     DirDescendant::new("child2", "child2", "child2", ()),
235    /// ]);
236    ///
237    /// assert_eq!(descendants.len(), 2);
238    /// assert_eq!(descendants.get_mut(0), Some(&mut DirDescendant::new("child1", "child1", "child1", ())));
239    /// assert_eq!(descendants.get_mut(1), Some(&mut DirDescendant::new("child2", "child2", "child2", ())));
240    /// assert_eq!(descendants.get_mut(2), None);
241    /// assert_eq!(descendants.get_mut(100), None);
242    /// ```
243    pub fn get_mut(&mut self, index: usize) -> Option<&mut DirDescendant<T, P>> {
244        self.descendants.get_mut(index)
245    }
246
247    /// Returns the descendant with the given name, or `None` if not found.
248    ///
249    /// # Examples
250    ///
251    /// ```
252    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
253    ///
254    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
255    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
256    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
257    /// ]);
258    ///
259    /// assert_eq!(descendants.get_by_name("child1"), Some(&DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
260    /// assert_eq!(descendants.get_by_name("child2"), Some(&DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
261    /// assert_eq!(descendants.get_by_name("child3"), None);
262    /// assert_eq!(descendants.get_by_name("nonexistent"), None);
263    /// ```
264    pub fn get_by_name(&self, name: impl AsRef<P::PathSegmentRef>) -> Option<&DirDescendant<T, P>>
265    where
266        P::PathSegmentRef: PartialEq,
267    {
268        self.iter().find(|d| d.name.as_ref() == name.as_ref())
269    }
270
271    /// Returns a mutable reference to the descendant with the given name, or `None` if not found.
272    /// This is a mutable version of [`get_by_name`](Self::get_by_name).
273    ///
274    /// # Examples
275    ///
276    /// ```
277    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
278    ///
279    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
280    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
281    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
282    /// ]);
283    ///
284    /// assert_eq!(descendants.get_by_name_mut("child1"), Some(&mut DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
285    /// assert_eq!(descendants.get_by_name_mut("child2"), Some(&mut DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
286    /// assert_eq!(descendants.get_by_name_mut("child3"), None);
287    /// assert_eq!(descendants.get_by_name_mut("nonexistent"), None);
288    /// ```
289    pub fn get_by_name_mut(
290        &mut self,
291        name: impl AsRef<P::PathSegmentRef>,
292    ) -> Option<&mut DirDescendant<T, P>>
293    where
294        P::PathSegmentRef: PartialEq,
295    {
296        self.iter_mut().find(|d| d.name.as_ref() == name.as_ref())
297    }
298
299    /// Returns the value of the descendant with the given name, or `None` if not found.
300    ///
301    /// # Examples
302    ///
303    /// ```
304    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
305    ///
306    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
307    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
308    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
309    /// ]);
310    ///
311    /// assert_eq!(descendants.get_value_by_name("child1"), Some(&"value1".into()));
312    /// assert_eq!(descendants.get_value_by_name("child2"), Some(&"value2".into()));
313    /// assert_eq!(descendants.get_value_by_name("child3"), None);
314    /// assert_eq!(descendants.get_value_by_name("nonexistent"), None);
315    /// ```
316    pub fn get_value_by_name(&self, name: impl AsRef<P::PathSegmentRef>) -> Option<&T>
317    where
318        P::PathSegmentRef: PartialEq,
319    {
320        self.get_by_name(name).map(|d| &d.value)
321    }
322
323    /// Returns a mutable reference to the value of the descendant with the given name, or `None` if not found.
324    /// This is a mutable version of [`get_value_by_name`](Self::get_value_by_name).
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
330    ///
331    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
332    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
333    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
334    /// ]);
335    ///
336    /// assert_eq!(descendants.get_value_by_name_mut("child1"), Some(&mut "value1".into()));
337    /// assert_eq!(descendants.get_value_by_name_mut("child2"), Some(&mut "value2".into()));
338    /// assert_eq!(descendants.get_value_by_name_mut("child3"), None);
339    /// assert_eq!(descendants.get_value_by_name_mut("nonexistent"), None);
340    /// ```
341    pub fn get_value_by_name_mut(&mut self, name: impl AsRef<P::PathSegmentRef>) -> Option<&mut T>
342    where
343        P::PathSegmentRef: PartialEq,
344    {
345        self.get_by_name_mut(name).map(|d| &mut d.value)
346    }
347
348    /// Returns the descendant with the given path, or `None` if not found.
349    ///
350    /// # Examples
351    ///
352    /// ```
353    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
354    ///
355    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
356    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
357    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
358    /// ]);
359    ///
360    /// assert_eq!(descendants.get_by_path("root/a/b/child1"), Some(&DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
361    /// assert_eq!(descendants.get_by_path("root/a/b/child2"), Some(&DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
362    /// assert_eq!(descendants.get_by_path("root/a/b/child3"), None);
363    /// assert_eq!(descendants.get_by_path("nonexistent"), None);
364    /// ```
365    pub fn get_by_path(&self, path: impl AsRef<P>) -> Option<&DirDescendant<T, P>>
366    where
367        P: PartialEq,
368    {
369        self.iter().find(|d| d.path.as_ref() == path.as_ref())
370    }
371
372    /// Returns a mutable reference to the descendant with the given path, or `None` if not found.
373    /// This is a mutable version of [`get_by_path`](Self::get_by_path).
374    ///
375    /// # Examples
376    ///
377    /// ```
378    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
379    ///
380    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
381    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
382    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
383    /// ]);
384    ///
385    /// assert_eq!(descendants.get_by_path_mut("root/a/b/child1"), Some(&mut DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
386    /// assert_eq!(descendants.get_by_path_mut("root/a/b/child2"), Some(&mut DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
387    /// assert_eq!(descendants.get_by_path_mut("root/a/b/child3"), None);
388    /// assert_eq!(descendants.get_by_path_mut("nonexistent"), None);
389    /// ```
390    pub fn get_by_path_mut(&mut self, path: impl AsRef<P>) -> Option<&mut DirDescendant<T, P>>
391    where
392        P: PartialEq,
393    {
394        self.iter_mut().find(|d| d.path.as_ref() == path.as_ref())
395    }
396
397    /// Returns the value of the descendant with the given path, or `None` if not found.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
403    ///
404    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
405    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
406    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
407    /// ]);
408    ///
409    /// assert_eq!(descendants.get_value_by_path("root/a/b/child1"), Some(&"value1".into()));
410    /// assert_eq!(descendants.get_value_by_path("root/a/b/child2"), Some(&"value2".into()));
411    /// assert_eq!(descendants.get_value_by_path("root/a/b/child3"), None);
412    /// assert_eq!(descendants.get_value_by_path("nonexistent"), None);
413    /// ```
414    pub fn get_value_by_path(&self, path: impl AsRef<P>) -> Option<&T>
415    where
416        P: PartialEq,
417    {
418        self.get_by_path(path).map(|d| &d.value)
419    }
420
421    /// Returns a mutable reference to the value of the descendant with the given path, or `None` if not found.
422    /// This is a mutable version of [`get_value_by_path`](Self::get_value_by_path).
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
428    ///
429    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
430    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
431    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
432    /// ]);
433    ///
434    /// assert_eq!(descendants.get_value_by_path_mut("root/a/b/child1"), Some(&mut "value1".into()));
435    /// assert_eq!(descendants.get_value_by_path_mut("root/a/b/child2"), Some(&mut "value2".into()));
436    /// assert_eq!(descendants.get_value_by_path_mut("root/a/b/child3"), None);
437    /// assert_eq!(descendants.get_value_by_path_mut("nonexistent"), None);
438    /// ```
439    pub fn get_value_by_path_mut(&mut self, path: impl AsRef<P>) -> Option<&mut T>
440    where
441        P: PartialEq,
442    {
443        self.get_by_path_mut(path).map(|d| &mut d.value)
444    }
445
446    /// Returns the descendant with the given path relative to the ascendant, or `None` if not found.
447    ///
448    /// # Examples
449    ///
450    /// ```
451    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
452    ///
453    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
454    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
455    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
456    /// ]);
457    ///
458    /// assert_eq!(descendants.get_by_relative_path("a/b/child1"), Some(&DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
459    /// assert_eq!(descendants.get_by_relative_path("a/b/child2"), Some(&DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
460    /// assert_eq!(descendants.get_by_relative_path("a/b/child3"), None);
461    /// assert_eq!(descendants.get_by_relative_path("nonexistent"), None);
462    /// ```
463    pub fn get_by_relative_path(&self, path: impl AsRef<P>) -> Option<&DirDescendant<T, P>>
464    where
465        P: PartialEq,
466    {
467        self.iter()
468            .find(|d| d.path_relative_to_ascendant.as_ref() == path.as_ref())
469    }
470
471    /// Returns a mutable reference to the descendant with the given path relative to the ascendant, or `None` if not found.
472    /// This is a mutable version of [`get_by_relative_path`](Self::get_by_relative_path).
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
478    ///
479    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
480    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
481    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
482    /// ]);
483    ///
484    /// assert_eq!(descendants.get_by_relative_path_mut("a/b/child1"), Some(&mut DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into())));
485    /// assert_eq!(descendants.get_by_relative_path_mut("a/b/child2"), Some(&mut DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into())));
486    /// assert_eq!(descendants.get_by_relative_path_mut("a/b/child3"), None);
487    /// assert_eq!(descendants.get_by_relative_path_mut("nonexistent"), None);
488    /// ```
489    pub fn get_by_relative_path_mut(
490        &mut self,
491        path: impl AsRef<P>,
492    ) -> Option<&mut DirDescendant<T, P>>
493    where
494        P: PartialEq,
495    {
496        self.iter_mut()
497            .find(|d| d.path_relative_to_ascendant.as_ref() == path.as_ref())
498    }
499
500    /// Returns the value of the descendant with the given path relative to the ascendant, or `None` if not found.
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
506    ///
507    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
508    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
509    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
510    /// ]);
511    ///
512    /// assert_eq!(descendants.get_value_by_relative_path("a/b/child1"), Some(&"value1".into()));
513    /// assert_eq!(descendants.get_value_by_relative_path("a/b/child2"), Some(&"value2".into()));
514    /// assert_eq!(descendants.get_value_by_relative_path("a/b/child3"), None);
515    /// assert_eq!(descendants.get_value_by_relative_path("nonexistent"), None);
516    /// ```
517    pub fn get_value_by_relative_path(&self, path: impl AsRef<P>) -> Option<&T>
518    where
519        P: PartialEq,
520    {
521        self.get_by_relative_path(path).map(|d| &d.value)
522    }
523
524    /// Returns a mutable reference to the value of the descendant with the given path relative to the ascendant, or `None` if not found.
525    /// This is a mutable version of [`get_value_by_relative_path`](Self::get_value_by_relative_path).
526    ///
527    /// # Examples
528    ///
529    /// ```
530    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
531    ///
532    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
533    ///     DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".into()),
534    ///     DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2".into()),
535    /// ]);
536    ///
537    /// assert_eq!(descendants.get_value_by_relative_path_mut("a/b/child1"), Some(&mut "value1".into()));
538    /// assert_eq!(descendants.get_value_by_relative_path_mut("a/b/child2"), Some(&mut "value2".into()));
539    /// assert_eq!(descendants.get_value_by_relative_path_mut("a/b/child3"), None);
540    /// assert_eq!(descendants.get_value_by_relative_path_mut("nonexistent"), None);
541    /// ```
542    pub fn get_value_by_relative_path_mut(&mut self, path: impl AsRef<P>) -> Option<&mut T>
543    where
544        P: PartialEq,
545    {
546        self.get_by_relative_path_mut(path).map(|d| &mut d.value)
547    }
548
549    /// Maps the descendants to another type.
550    ///
551    /// # Examples
552    ///
553    /// ```
554    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
555    ///
556    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
557    ///   DirDescendant::new("child1", "root/a/b/child1", "a/b/child1", "value1".to_string()),
558    ///   DirDescendant::new("child2", "root/a/b/child2", "a/b/child2", "value2abc1000".to_string()),
559    /// ]);
560    ///
561    /// let mapped = descendants.map(|s| s.len());
562    /// assert_eq!(mapped.len(), 2);
563    /// assert_eq!(mapped.get(0).unwrap().value(), &6); // "value1".len() == 6
564    /// assert_eq!(mapped.get(1).unwrap().value(), &13); // "value2abc1000".len() == 13
565    /// assert_eq!(mapped.get(2), None);
566    /// assert_eq!(mapped.get(100), None);
567    /// ```
568    pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> DirDescendants<U, F, P> {
569        DirDescendants {
570            descendants: self
571                .descendants
572                .into_iter()
573                .map(move |d| DirDescendant {
574                    name: d.name,
575                    path: d.path,
576                    path_relative_to_ascendant: d.path_relative_to_ascendant,
577                    value: f(d.value),
578                })
579                .collect(),
580            _phantom: marker::PhantomData,
581        }
582    }
583
584    /// Maps the filter type to another type.
585    ///
586    /// # Examples
587    ///
588    /// ```
589    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant, FileFilter, FolderFilter, FolderRecurseFilter}, NoFilter};
590    ///
591    /// struct MyFilter;
592    ///
593    /// impl FileFilter for MyFilter {
594    ///     fn allows(_file: &std::path::Path) -> bool { true }
595    /// }
596    /// impl FolderFilter for MyFilter {
597    ///     fn allows(_folder: &std::path::Path) -> bool { true }
598    /// }
599    /// impl FolderRecurseFilter for MyFilter {
600    ///     fn allows(_folder: &std::path::Path) -> bool { true }
601    /// }
602    ///
603    /// let descendants = DirDescendants::<String, NoFilter>::new(vec![
604    ///     DirDescendant::new("child1", "child1", "child1", "value1".to_string()),
605    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
606    /// ]);
607    /// let descendants_with_my_filter: DirDescendants<String, MyFilter> = descendants.map_filter::<MyFilter>();
608    /// ```
609    pub fn map_filter<F2: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>>(
610        self,
611    ) -> DirDescendants<T, F2, P> {
612        DirDescendants {
613            descendants: self.descendants,
614            _phantom: marker::PhantomData,
615        }
616    }
617
618    /// Appends a descendant to the end of the list.
619    ///
620    /// # Examples
621    ///
622    /// ```
623    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
624    ///
625    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![]);
626    /// assert!(descendants.is_empty());
627    ///
628    /// descendants.push(DirDescendant::new("child1", "child1", "child1", "value1".to_string()));
629    /// assert_eq!(descendants.len(), 1);
630    /// let mut i = descendants.iter();
631    /// assert_eq!(i.next(), Some(&DirDescendant::new("child1", "child1", "child1", "value1".to_string())));
632    /// assert_eq!(i.next(), None);
633    ///
634    /// descendants.push(DirDescendant::new("child2", "child2", "child2", "value2".to_string()));
635    /// assert_eq!(descendants.len(), 2);
636    /// let mut i = descendants.iter();
637    /// assert_eq!(i.next(), Some(&DirDescendant::new("child1", "child1", "child1", "value1".to_string())));
638    /// assert_eq!(i.next(), Some(&DirDescendant::new("child2", "child2", "child2", "value2".to_string())));
639    /// assert_eq!(i.next(), None);
640    /// ```
641    pub fn push(&mut self, descendant: DirDescendant<T, P>) {
642        self.descendants.push(descendant);
643    }
644
645    /// Retains only the descendants specified by the predicate.
646    ///
647    /// # Examples
648    ///
649    /// ```
650    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
651    ///
652    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
653    ///     DirDescendant::new("child1", "child1", "child1", "value1".to_string()),
654    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
655    ///     DirDescendant::new("child3", "child3", "child3", "value3".to_string()),
656    /// ]);
657    ///
658    /// descendants.retain(|d| d.name() == "child2");
659    /// assert_eq!(descendants.len(), 1);
660    /// assert_eq!(descendants.get(0).unwrap().name(), "child2");
661    /// ```
662    pub fn retain(&mut self, f: impl FnMut(&DirDescendant<T, P>) -> bool) {
663        self.descendants.retain(f);
664    }
665
666    /// Drains the descendants in the specified range.
667    ///
668    /// # Examples
669    ///
670    /// ```
671    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
672    ///
673    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
674    ///     DirDescendant::new("child1", "child1", "child1", "value1".to_string()),
675    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
676    ///     DirDescendant::new("child3", "child3", "child3", "value3".to_string()),
677    /// ]);
678    ///
679    /// let drained: Vec<_> = descendants.drain(0..2).collect();
680    /// assert_eq!(drained, vec![
681    ///     DirDescendant::new("child1", "child1", "child1", "value1".to_string()),
682    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
683    /// ]);
684    /// assert_eq!(descendants.len(), 1);
685    /// assert_eq!(descendants.get(0).unwrap().name(), "child3");
686    /// ```
687    pub fn drain(&mut self, range: impl ops::RangeBounds<usize>) -> DirDescendantsDrain<'_, T, P> {
688        DirDescendantsDrain(self.descendants.drain(range))
689    }
690
691    /// Extracts the descendants in the specified range that satisfy the predicate.
692    ///
693    /// # Examples
694    ///
695    /// ```
696    /// use dir_structure::{dir_descendants::{DirDescendants, DirDescendant}, NoFilter};
697    ///
698    /// let mut descendants = DirDescendants::<String, NoFilter>::new(vec![
699    ///     DirDescendant::new("child1", "child1", "child1", "value1".to_string()),
700    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
701    ///     DirDescendant::new("child3", "child3", "child3", "value3".to_string()),
702    ///     DirDescendant::new("child4", "child4", "child4", "value4".to_string()),
703    /// ]);
704    ///
705    /// let extracted: Vec<_> = descendants.extract_if(1..4, |d| d.name() == "child2" || d.name() == "child4").collect();
706    /// assert_eq!(extracted, vec![
707    ///     DirDescendant::new("child2", "child2", "child2", "value2".to_string()),
708    ///     DirDescendant::new("child4", "child4", "child4", "value4".to_string()),
709    /// ]);
710    /// assert_eq!(descendants.len(), 2);
711    /// assert_eq!(descendants.get(0).unwrap().name(), "child1");
712    /// assert_eq!(descendants.get(1).unwrap().name(), "child3");
713    /// ```
714    pub fn extract_if<'a, Fi>(
715        &'a mut self,
716        range: impl ops::RangeBounds<usize>,
717        f: Fi,
718    ) -> DirDescendantsExtractIf<'a, T, P, Fi>
719    where
720        Fi: FnMut(&mut DirDescendant<T, P>) -> bool,
721    {
722        DirDescendantsExtractIf(self.descendants.extract_if(range, f))
723    }
724}
725
726impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized> Default
727    for DirDescendants<T, F, P>
728{
729    fn default() -> Self {
730        Self::new(vec![])
731    }
732}
733
734impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
735    From<Vec<DirDescendant<T, P>>> for DirDescendants<T, F, P>
736{
737    fn from(descendants: Vec<DirDescendant<T, P>>) -> Self {
738        Self::new(descendants)
739    }
740}
741
742impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
743    FromIterator<DirDescendant<T, P>> for DirDescendants<T, F, P>
744{
745    fn from_iter<I: IntoIterator<Item = DirDescendant<T, P>>>(iter: I) -> Self {
746        Self::new(iter.into_iter().collect())
747    }
748}
749
750impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
751    Extend<DirDescendant<T, P>> for DirDescendants<T, F, P>
752{
753    fn extend<I: IntoIterator<Item = DirDescendant<T, P>>>(&mut self, iter: I) {
754        self.descendants.extend(iter);
755    }
756}
757
758impl<'a, T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
759    IntoIterator for &'a DirDescendants<T, F, P>
760{
761    type Item = &'a DirDescendant<T, P>;
762    type IntoIter = DirDescendantsIter<'a, T, P>;
763
764    fn into_iter(self) -> Self::IntoIter {
765        self.iter()
766    }
767}
768
769impl<'a, T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
770    IntoIterator for &'a mut DirDescendants<T, F, P>
771{
772    type Item = &'a mut DirDescendant<T, P>;
773    type IntoIter = DirDescendantsIterMut<'a, T, P>;
774
775    fn into_iter(self) -> Self::IntoIter {
776        self.iter_mut()
777    }
778}
779
780impl<T, F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P>, P: PathType + ?Sized>
781    IntoIterator for DirDescendants<T, F, P>
782{
783    type Item = DirDescendant<T, P>;
784    type IntoIter = DirDescendantsIntoIter<T, P>;
785
786    fn into_iter(self) -> Self::IntoIter {
787        DirDescendantsIntoIter(self.descendants.into_iter())
788    }
789}
790
791/// An iterator over the immutable descendants.
792pub struct DirDescendantsIter<'a, T, P: PathType + ?Sized>(slice::Iter<'a, DirDescendant<T, P>>);
793
794impl<'a, T, P: PathType + ?Sized> Iterator for DirDescendantsIter<'a, T, P> {
795    type Item = &'a DirDescendant<T, P>;
796
797    fn next(&mut self) -> Option<Self::Item> {
798        self.0.next()
799    }
800
801    fn size_hint(&self) -> (usize, Option<usize>) {
802        self.0.size_hint()
803    }
804}
805
806impl<'a, T, P: PathType + ?Sized> DoubleEndedIterator for DirDescendantsIter<'a, T, P> {
807    fn next_back(&mut self) -> Option<Self::Item> {
808        self.0.next_back()
809    }
810}
811
812impl<'a, T, P: PathType + ?Sized> ExactSizeIterator for DirDescendantsIter<'a, T, P> {
813    fn len(&self) -> usize {
814        self.0.len()
815    }
816}
817
818/// An iterator over the mutable descendants.
819pub struct DirDescendantsIterMut<'a, T, P: PathType + ?Sized>(
820    slice::IterMut<'a, DirDescendant<T, P>>,
821);
822
823impl<'a, T, P: PathType + ?Sized> Iterator for DirDescendantsIterMut<'a, T, P> {
824    type Item = &'a mut DirDescendant<T, P>;
825
826    fn next(&mut self) -> Option<Self::Item> {
827        self.0.next()
828    }
829
830    fn size_hint(&self) -> (usize, Option<usize>) {
831        self.0.size_hint()
832    }
833}
834
835impl<'a, T, P: PathType + ?Sized> DoubleEndedIterator for DirDescendantsIterMut<'a, T, P> {
836    fn next_back(&mut self) -> Option<Self::Item> {
837        self.0.next_back()
838    }
839}
840
841impl<'a, T, P: PathType + ?Sized> ExactSizeIterator for DirDescendantsIterMut<'a, T, P> {
842    fn len(&self) -> usize {
843        self.0.len()
844    }
845}
846
847/// An iterator over the owned descendants.
848pub struct DirDescendantsIntoIter<T, P: PathType + ?Sized>(vec::IntoIter<DirDescendant<T, P>>);
849
850impl<'a, T, P: PathType + ?Sized> Iterator for DirDescendantsIntoIter<T, P> {
851    type Item = DirDescendant<T, P>;
852
853    fn next(&mut self) -> Option<Self::Item> {
854        self.0.next()
855    }
856
857    fn size_hint(&self) -> (usize, Option<usize>) {
858        self.0.size_hint()
859    }
860}
861
862impl<'a, T, P: PathType + ?Sized> DoubleEndedIterator for DirDescendantsIntoIter<T, P> {
863    fn next_back(&mut self) -> Option<Self::Item> {
864        self.0.next_back()
865    }
866}
867
868impl<'a, T, P: PathType + ?Sized> ExactSizeIterator for DirDescendantsIntoIter<T, P> {
869    fn len(&self) -> usize {
870        self.0.len()
871    }
872}
873
874/// An iterator that drains the owned descendants.
875///
876/// See [`DirDescendants::drain`].
877pub struct DirDescendantsDrain<'a, T, P: PathType + ?Sized>(vec::Drain<'a, DirDescendant<T, P>>);
878
879impl<T, P: PathType + ?Sized> Iterator for DirDescendantsDrain<'_, T, P> {
880    type Item = DirDescendant<T, P>;
881
882    fn next(&mut self) -> Option<Self::Item> {
883        self.0.next()
884    }
885
886    fn size_hint(&self) -> (usize, Option<usize>) {
887        self.0.size_hint()
888    }
889}
890
891impl<T, P: PathType + ?Sized> DoubleEndedIterator for DirDescendantsDrain<'_, T, P> {
892    fn next_back(&mut self) -> Option<Self::Item> {
893        self.0.next_back()
894    }
895}
896
897impl<T, P: PathType + ?Sized> ExactSizeIterator for DirDescendantsDrain<'_, T, P> {
898    fn len(&self) -> usize {
899        self.0.len()
900    }
901}
902
903/// An iterator that extracts the owned descendants that satisfy the predicate.
904///
905/// See [`DirDescendants::extract_if`].
906pub struct DirDescendantsExtractIf<
907    'a,
908    T,
909    P: PathType + ?Sized,
910    F: FnMut(&mut DirDescendant<T, P>) -> bool,
911>(vec::ExtractIf<'a, DirDescendant<T, P>, F>);
912
913impl<T, P: PathType + ?Sized, F: FnMut(&mut DirDescendant<T, P>) -> bool> Iterator
914    for DirDescendantsExtractIf<'_, T, P, F>
915{
916    type Item = DirDescendant<T, P>;
917
918    fn next(&mut self) -> Option<Self::Item> {
919        self.0.next()
920    }
921
922    fn size_hint(&self) -> (usize, Option<usize>) {
923        self.0.size_hint()
924    }
925}
926
927impl<
928    'vfs,
929    Vfs: vfs::Vfs<'vfs>,
930    T: ReadFrom<'vfs, Vfs>,
931    F: FolderFilter<Vfs::Path> + FolderRecurseFilter<Vfs::Path> + FileFilter<Vfs::Path> + 'vfs,
932> ReadFrom<'vfs, Vfs> for DirDescendants<T, F, Vfs::Path>
933{
934    fn read_from(path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<Self, Vfs> {
935        let mut descendants = Vec::new();
936
937        if vfs.is_dir(path)? {
938            let mut walker = vfs.walk_dir(path)?;
939            while let Some(entry) = walker.next() {
940                let DirEntryInfo {
941                    name,
942                    path: entry_path,
943                    kind,
944                } = entry?;
945
946                if kind.is_dir() {
947                    if <F as FolderRecurseFilter<Vfs::Path>>::allows(entry_path.as_ref()) {
948                        let sub_descendants =
949                            DirDescendants::<T, F, Vfs::Path>::read_from(entry_path.as_ref(), vfs)?;
950                        descendants.extend(sub_descendants.descendants.into_iter().map(
951                            |mut it| {
952                                it.path_relative_to_ascendant.insert_in_front(name.as_ref());
953                                it
954                            },
955                        ));
956                    }
957
958                    if <F as FolderFilter<Vfs::Path>>::allows(entry_path.as_ref()) {
959                        let value = T::read_from(entry_path.as_ref(), vfs)?;
960                        descendants.push(DirDescendant {
961                            name,
962                            path_relative_to_ascendant: entry_path
963                                .as_ref()
964                                .strip_prefix(path)
965                                .unwrap()
966                                .owned(),
967                            path: entry_path,
968                            value,
969                        });
970                    }
971                } else if kind.is_file()
972                    && <F as FileFilter<Vfs::Path>>::allows(entry_path.as_ref())
973                {
974                    let value = T::read_from(entry_path.as_ref(), vfs)?;
975                    descendants.push(DirDescendant {
976                        name,
977                        path_relative_to_ascendant: entry_path
978                            .as_ref()
979                            .strip_prefix(path)
980                            .unwrap()
981                            .owned(),
982                        path: entry_path,
983                        value,
984                    });
985                }
986            }
987        }
988
989        Ok(DirDescendants::new(descendants))
990    }
991}
992
993#[cfg(feature = "async")]
994#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
995impl<
996    'vfs,
997    P: PathType + ?Sized + 'vfs,
998    Vfs: VfsAsync<Path = P> + 'static,
999    T: ReadFromAsync<'vfs, Vfs> + Send + 'static,
1000    F: FolderFilter<P> + FolderRecurseFilter<P> + FileFilter<P> + 'vfs,
1001> ReadFromAsync<'vfs, Vfs> for DirDescendants<T, F, P>
1002where
1003    for<'f> Vfs::IsDirFuture<'f>: Future<Output = VfsResult<bool, Vfs>> + Send + 'f,
1004{
1005    type Future
1006        = BoxFuture<'vfs, VfsResult<Self, Vfs>>
1007    where
1008        Self: 'vfs;
1009
1010    fn read_from_async(path: P::OwnedPath, vfs: Pin<&'vfs Vfs>) -> Self::Future {
1011        Box::pin(async move {
1012            let mut descendants = Vec::new();
1013
1014            if vfs.is_dir(path.clone()).await? {
1015                use std::pin::pin;
1016
1017                use futures::StreamExt;
1018
1019                let mut walker = pin!(vfs.walk_dir(path.clone()).await?);
1020                while let Some(entry) = walker.next().await {
1021                    let DirEntryInfo {
1022                        name,
1023                        path: entry_path,
1024                        kind,
1025                    } = entry?;
1026
1027                    if kind.is_dir() {
1028                        if <F as FolderRecurseFilter<P>>::allows(entry_path.as_ref()) {
1029                            let sub_descendants =
1030                                DirDescendants::<T, F, P>::read_from_async(entry_path.clone(), vfs)
1031                                    .await?;
1032                            descendants.extend(sub_descendants.descendants.into_iter().map(
1033                                |mut it| {
1034                                    it.path_relative_to_ascendant.insert_in_front(name.as_ref());
1035                                    it
1036                                },
1037                            ));
1038                        }
1039
1040                        if <F as FolderFilter<P>>::allows(entry_path.as_ref()) {
1041                            let value = T::read_from_async(entry_path.clone(), vfs).await?;
1042                            descendants.push(DirDescendant {
1043                                name,
1044                                path_relative_to_ascendant: entry_path
1045                                    .as_ref()
1046                                    .strip_prefix(path.as_ref())
1047                                    .unwrap()
1048                                    .owned(),
1049                                path: entry_path,
1050                                value,
1051                            });
1052                        }
1053                    } else if kind.is_file() && <F as FileFilter<P>>::allows(entry_path.as_ref()) {
1054                        let value = T::read_from_async(entry_path.clone(), vfs).await?;
1055                        descendants.push(DirDescendant {
1056                            name,
1057                            path_relative_to_ascendant: entry_path
1058                                .as_ref()
1059                                .strip_prefix(path.as_ref())
1060                                .unwrap()
1061                                .owned(),
1062                            path: entry_path,
1063                            value,
1064                        });
1065                    }
1066                }
1067            }
1068
1069            Ok(DirDescendants::new(descendants))
1070        })
1071    }
1072}
1073
1074impl<
1075    'vfs,
1076    Vfs: vfs::WriteSupportingVfs<'vfs>,
1077    T: WriteTo<'vfs, Vfs> + 'vfs,
1078    F: FileFilter<Vfs::Path> + FolderRecurseFilter<Vfs::Path> + FolderFilter<Vfs::Path> + 'vfs,
1079> WriteTo<'vfs, Vfs> for DirDescendants<T, F, Vfs::Path>
1080{
1081    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
1082        for descendant in &self.descendants {
1083            descendant.value.write_to(
1084                path.join(&descendant.path_relative_to_ascendant).as_ref(),
1085                vfs,
1086            )?;
1087        }
1088        Ok(())
1089    }
1090}
1091
1092#[cfg(feature = "async")]
1093#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1094impl<
1095    'vfs,
1096    Vfs: WriteSupportingVfsAsync + 'vfs,
1097    T: WriteToAsync<'vfs, Vfs> + Send + 'vfs,
1098    F: FileFilter<Vfs::Path> + FolderRecurseFilter<Vfs::Path> + FolderFilter<Vfs::Path> + Send + 'vfs,
1099> WriteToAsync<'vfs, Vfs> for DirDescendants<T, F, Vfs::Path>
1100{
1101    type Future = BoxFuture<'vfs, VfsResult<(), Vfs>>;
1102
1103    fn write_to_async(
1104        self,
1105        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1106        vfs: Pin<&'vfs Vfs>,
1107    ) -> Self::Future {
1108        Box::pin(async move {
1109            for descendant in self {
1110                descendant
1111                    .value
1112                    .write_to_async(
1113                        path.as_ref().join(descendant.path_relative_to_ascendant),
1114                        vfs,
1115                    )
1116                    .await?;
1117            }
1118            Ok(())
1119        })
1120    }
1121}
1122
1123#[cfg(feature = "async")]
1124#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1125#[pin_project(project_replace = DirDescendantsWriteRefFutureProj)]
1126#[doc(hidden)]
1127pub enum DirDescendantsWriteRefFuture<
1128    'a,
1129    'vfs: 'a,
1130    Vfs: WriteSupportingVfsAsync + 'vfs,
1131    T: WriteToAsyncRef<'vfs, Vfs> + 'vfs,
1132> where
1133    T::Future<'a>: Future<Output = VfsResult<(), Vfs>> + Unpin + 'a,
1134{
1135    Poison,
1136    Writing {
1137        vfs: Pin<&'a Vfs>,
1138        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1139        iter: DirDescendantsIter<'a, T, Vfs::Path>,
1140        future: T::Future<'a>,
1141    },
1142    NoElems,
1143}
1144
1145#[cfg(feature = "async")]
1146#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1147impl<'a, 'vfs: 'a, Vfs: WriteSupportingVfsAsync + 'vfs, T: WriteToAsyncRef<'vfs, Vfs> + 'vfs> Future
1148    for DirDescendantsWriteRefFuture<'a, 'vfs, Vfs, T>
1149where
1150    for<'r> T::Future<'r>: Future<Output = VfsResult<(), Vfs>> + Unpin + 'r,
1151{
1152    type Output = VfsResult<(), Vfs>;
1153
1154    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1155        let this = self.as_mut().project_replace(Self::Poison);
1156        match this {
1157            DirDescendantsWriteRefFutureProj::Poison => {
1158                panic!("polled after completion")
1159            }
1160            DirDescendantsWriteRefFutureProj::Writing {
1161                vfs,
1162                path,
1163                mut iter,
1164                mut future,
1165            } => match Pin::new(&mut future).poll(cx) {
1166                Poll::Ready(Ok(())) => {
1167                    let next = iter.next();
1168                    if let Some(descendant) = next {
1169                        let future = descendant.value.write_to_async_ref(
1170                            path.as_ref().join(&descendant.path_relative_to_ascendant),
1171                            vfs,
1172                        );
1173                        self.as_mut()
1174                            .project_replace(DirDescendantsWriteRefFuture::Writing {
1175                                vfs,
1176                                path,
1177                                iter,
1178                                future,
1179                            });
1180                        cx.waker().wake_by_ref();
1181                        Poll::Pending
1182                    } else {
1183                        Poll::Ready(Ok(()))
1184                    }
1185                }
1186                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
1187                Poll::Pending => {
1188                    self.as_mut()
1189                        .project_replace(DirDescendantsWriteRefFuture::Writing {
1190                            vfs,
1191                            path,
1192                            iter,
1193                            future,
1194                        });
1195                    Poll::Pending
1196                }
1197            },
1198            DirDescendantsWriteRefFutureProj::NoElems => Poll::Ready(Ok(())),
1199        }
1200    }
1201}
1202
1203#[cfg(feature = "async")]
1204#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1205impl<
1206    'vfs,
1207    Vfs: WriteSupportingVfsAsync<Path = P> + 'static,
1208    P: ?Sized + vfs::PathType,
1209    T: WriteToAsyncRef<'vfs, Vfs> + Sync + 'static,
1210    F: FileFilter<P> + FolderRecurseFilter<P> + FolderFilter<P> + Sync + 'vfs,
1211> WriteToAsyncRef<'vfs, Vfs> for DirDescendants<T, F, P>
1212where
1213    for<'r> T::Future<'r>: Future<Output = VfsResult<(), Vfs>> + Unpin + 'r,
1214{
1215    type Future<'r>
1216        = DirDescendantsWriteRefFuture<'r, 'vfs, Vfs, T>
1217    where
1218        'vfs: 'r,
1219        Self: 'r,
1220        Vfs: 'r,
1221        T: 'r;
1222
1223    fn write_to_async_ref<'r>(&'r self, path: P::OwnedPath, vfs: Pin<&'r Vfs>) -> Self::Future<'r>
1224    where
1225        'vfs: 'r,
1226    {
1227        let mut iter = self.iter();
1228        if let Some(first) = iter.next() {
1229            let future = first
1230                .value
1231                .write_to_async_ref(path.as_ref().join(&first.path_relative_to_ascendant), vfs);
1232            DirDescendantsWriteRefFuture::Writing {
1233                vfs,
1234                iter,
1235                future,
1236                path,
1237            }
1238        } else {
1239            DirDescendantsWriteRefFuture::NoElems
1240        }
1241    }
1242}
1243
1244/// A filter for folders, see the [`DirDescendants`] documentation.
1245pub trait FolderFilter<P: PathType + ?Sized = Path> {
1246    /// Whether to allow the given path.
1247    fn allows(folder: &P) -> bool;
1248}
1249
1250impl<P: PathType + ?Sized> FolderFilter<P> for NoFilter {
1251    fn allows(_folder: &P) -> bool {
1252        true
1253    }
1254}
1255
1256/// A filter to tell the reading logic whether to recurse into a folder, see the [`DirDescendants`] documentation.
1257pub trait FolderRecurseFilter<P: PathType + ?Sized = Path> {
1258    /// Whether to allow the given path.
1259    fn allows(folder: &P) -> bool;
1260}
1261
1262impl<P: PathType + ?Sized> FolderRecurseFilter<P> for NoFilter {
1263    fn allows(_folder: &P) -> bool {
1264        true
1265    }
1266}
1267
1268/// A filter for files, see the [`DirDescendants`] documentation.
1269pub trait FileFilter<P: PathType + ?Sized = Path> {
1270    /// Whether to allow the given path.
1271    fn allows(file: &P) -> bool;
1272}
1273
1274impl<P: PathType + ?Sized> FileFilter<P> for NoFilter {
1275    fn allows(_file: &P) -> bool {
1276        true
1277    }
1278}
1279
1280/// A single directory descendant, identified by its path relative to the ascendant.
1281///
1282/// It also stores the path relative to the "root."
1283#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
1284#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
1285pub struct DirDescendant<T, P: PathType + ?Sized = Path> {
1286    name: P::PathSegmentOwned,
1287    path: P::OwnedPath,
1288    path_relative_to_ascendant: P::OwnedPath,
1289    value: T,
1290}
1291
1292impl<T: fmt::Debug, P: PathType + ?Sized> fmt::Debug for DirDescendant<T, P>
1293where
1294    P::PathSegmentOwned: fmt::Debug,
1295    P::OwnedPath: fmt::Debug,
1296{
1297    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1298        f.debug_struct("DirDescendant")
1299            .field("name", &self.name)
1300            .field("path", &self.path)
1301            .field(
1302                "path_relative_to_ascendant",
1303                &self.path_relative_to_ascendant,
1304            )
1305            .field("value", &self.value)
1306            .finish()
1307    }
1308}
1309
1310impl<T: Clone, P: PathType + ?Sized> Clone for DirDescendant<T, P>
1311where
1312    P::PathSegmentOwned: Clone,
1313    P::OwnedPath: Clone,
1314{
1315    fn clone(&self) -> Self {
1316        Self {
1317            name: self.name.clone(),
1318            path: self.path.clone(),
1319            path_relative_to_ascendant: self.path_relative_to_ascendant.clone(),
1320            value: self.value.clone(),
1321        }
1322    }
1323}
1324
1325impl<T, P: PathType + ?Sized> DirDescendant<T, P> {
1326    /// Create a new directory descendant from its parts.
1327    ///
1328    /// # Examples
1329    ///
1330    /// ```
1331    /// use std::ffi::OsString;
1332    /// use std::path::Path;
1333    /// use std::path::PathBuf;
1334    /// use dir_structure::dir_descendants::DirDescendant;
1335    ///
1336    /// let descendant = DirDescendant::<_, Path>::new(
1337    ///     "child".to_owned(),
1338    ///     "root/a/b/child".to_owned(),
1339    ///     "a/b/child".to_owned(),
1340    ///     String::from("child_value"),
1341    /// );
1342    /// assert_eq!(descendant.name(), &OsString::from("child"));
1343    /// assert_eq!(descendant.path(), &PathBuf::from("root/a/b/child"));
1344    /// assert_eq!(descendant.path_relative_to_ascendant(), &PathBuf::from("a/b/child"));
1345    /// assert_eq!(descendant.value(), &String::from("child_value"));
1346    /// ```
1347    pub fn new(
1348        name: impl Into<P::PathSegmentOwned>,
1349        path: impl Into<P::OwnedPath>,
1350        path_relative_to_ascendant: impl Into<P::OwnedPath>,
1351        value: T,
1352    ) -> Self {
1353        Self {
1354            name: name.into(),
1355            path: path.into(),
1356            path_relative_to_ascendant: path_relative_to_ascendant.into(),
1357            value,
1358        }
1359    }
1360
1361    /// Get the name of the directory descendant.
1362    ///
1363    /// # Examples
1364    ///
1365    /// ```
1366    /// use std::ffi::OsString;
1367    /// use std::path::Path;
1368    /// use dir_structure::dir_descendants::DirDescendant;
1369    ///
1370    /// let descendant = DirDescendant::<_, Path>::new(
1371    ///     "child",
1372    ///     "root/a/b/child",
1373    ///     "a/b/child",
1374    ///     String::from("child_value"),
1375    /// );
1376    /// assert_eq!(descendant.name(), &OsString::from("child"));
1377    /// ```
1378    pub fn name(&self) -> &P::PathSegmentOwned {
1379        &self.name
1380    }
1381
1382    /// Get the path of the directory descendant.
1383    ///
1384    /// # Examples
1385    ///
1386    /// ```
1387    /// use std::path::PathBuf;
1388    /// use std::path::Path;
1389    /// use dir_structure::dir_descendants::DirDescendant;
1390    ///
1391    /// let descendant = DirDescendant::<_, Path>::new(
1392    ///     "child",
1393    ///     "root/a/b/child",
1394    ///     "a/b/child",
1395    ///     String::from("child_value"),
1396    /// );
1397    /// assert_eq!(descendant.path(), &PathBuf::from("root/a/b/child"));
1398    /// ```
1399    pub fn path(&self) -> &P {
1400        self.path.as_ref()
1401    }
1402
1403    /// Get the path relative to the ascendant.
1404    ///
1405    /// # Examples
1406    ///
1407    /// ```
1408    /// use std::path::PathBuf;
1409    /// use std::path::Path;
1410    /// use dir_structure::dir_descendants::DirDescendant;
1411    ///
1412    /// let descendant = DirDescendant::<_, Path>::new(
1413    ///     "child",
1414    ///     "root/a/b/child",
1415    ///     "a/b/child",
1416    ///     String::from("child_value"),
1417    /// );
1418    /// assert_eq!(descendant.path_relative_to_ascendant(), &PathBuf::from("a/b/child"));
1419    /// ```
1420    pub fn path_relative_to_ascendant(&self) -> &P {
1421        self.path_relative_to_ascendant.as_ref()
1422    }
1423
1424    /// Get the value of the descendant.
1425    ///
1426    /// # Examples
1427    ///
1428    /// ```
1429    /// use std::path::PathBuf;
1430    /// use std::path::Path;
1431    /// use dir_structure::dir_descendants::DirDescendant;
1432    ///
1433    /// let descendant = DirDescendant::<_, Path>::new(
1434    ///     "child",
1435    ///     "root/a/b/child",
1436    ///     "a/b/child",
1437    ///     String::from("child_value"),
1438    /// );
1439    /// assert_eq!(descendant.value(), &String::from("child_value"));
1440    /// ```
1441    pub fn value(&self) -> &T {
1442        &self.value
1443    }
1444
1445    /// Turns the descendant into its value.
1446    ///
1447    /// # Examples
1448    ///
1449    /// ```
1450    /// use std::path::Path;
1451    /// use dir_structure::dir_descendants::DirDescendant;
1452    ///
1453    /// let descendant = DirDescendant::<_, Path>::new(
1454    ///     "child",
1455    ///     "root/a/b/child",
1456    ///     "a/b/child",
1457    ///     String::from("child_value"),
1458    /// );
1459    /// assert_eq!(descendant.into_value(), String::from("child_value"));
1460    /// ```
1461    pub fn into_value(self) -> T {
1462        self.value
1463    }
1464
1465    /// Turns the descendant into its name.
1466    ///
1467    /// # Examples
1468    ///
1469    /// ```
1470    /// use std::ffi::OsString;
1471    /// use std::path::Path;
1472    /// use dir_structure::dir_descendants::DirDescendant;
1473    ///
1474    /// let descendant = DirDescendant::<_, Path>::new(
1475    ///     "child",
1476    ///     "root/a/b/child",
1477    ///     "a/b/child",
1478    ///     String::from("child_value"),
1479    /// );
1480    /// assert_eq!(descendant.into_name(), OsString::from("child"));
1481    /// ```
1482    pub fn into_name(self) -> P::PathSegmentOwned {
1483        self.name
1484    }
1485
1486    /// Turns the descendant into its path.
1487    ///
1488    /// # Examples
1489    ///
1490    /// ```
1491    /// use std::path::PathBuf;
1492    /// use std::path::Path;
1493    /// use dir_structure::dir_descendants::DirDescendant;
1494    ///
1495    /// let descendant = DirDescendant::<_, Path>::new(
1496    ///     "child",
1497    ///     "root/a/b/child",
1498    ///     "a/b/child",
1499    ///     String::from("child_value"),
1500    /// );
1501    /// assert_eq!(descendant.into_path(), PathBuf::from("root/a/b/child"));
1502    /// ```
1503    pub fn into_path(self) -> P::OwnedPath {
1504        self.path
1505    }
1506
1507    /// Get a mutable reference to the name of the directory descendant.
1508    /// This is a mutable version of [`DirDescendant::name`].
1509    ///
1510    /// # Examples
1511    ///
1512    /// ```
1513    /// use std::ffi::OsString;
1514    /// use std::path::Path;
1515    /// use dir_structure::dir_descendants::DirDescendant;
1516    ///
1517    /// let mut descendant = DirDescendant::<_, Path>::new(
1518    ///     "child",
1519    ///     "root/a/b/child",
1520    ///     "a/b/child",
1521    ///     String::from("child_value"),
1522    /// );
1523    /// *descendant.name_mut() = OsString::from("new_child");
1524    /// assert_eq!(descendant.name(), &OsString::from("new_child"));
1525    /// ```
1526    pub fn name_mut(&mut self) -> &mut P::PathSegmentOwned {
1527        &mut self.name
1528    }
1529
1530    /// Get a mutable reference to the value of the directory descendant.
1531    /// This is a mutable version of [`DirDescendant::value`].
1532    ///
1533    /// # Examples
1534    ///
1535    /// ```
1536    /// use std::path::Path;
1537    /// use dir_structure::dir_descendants::DirDescendant;
1538    ///
1539    /// let mut descendant = DirDescendant::<_, Path>::new(
1540    ///     "child",
1541    ///     "root/a/b/child",
1542    ///     "a/b/child",
1543    ///     String::from("child_value"),
1544    /// );
1545    /// *descendant.value_mut() = String::from("new_child_value");
1546    /// assert_eq!(descendant.value(), &String::from("new_child_value"));
1547    /// ```
1548    pub fn value_mut(&mut self) -> &mut T {
1549        &mut self.value
1550    }
1551
1552    /// Clones the directory name and paths, but makes the value a reference to the original value.
1553    ///
1554    /// # Examples
1555    ///
1556    /// ```
1557    /// use std::path::Path;
1558    /// use dir_structure::dir_descendants::DirDescendant;
1559    ///
1560    /// let descendant = DirDescendant::<_, Path>::new(
1561    ///     "child",
1562    ///     "root/a/b/child",
1563    ///     "a/b/child",
1564    ///     String::from("child_value"),
1565    /// );
1566    ///
1567    /// let ref_descendant = descendant.as_ref();
1568    /// assert_eq!(ref_descendant.name(), descendant.name());
1569    /// assert_eq!(ref_descendant.path(), descendant.path());
1570    /// assert_eq!(ref_descendant.path_relative_to_ascendant(), descendant.path_relative_to_ascendant());
1571    /// assert_eq!(ref_descendant.value(), &descendant.value());
1572    /// ```
1573    pub fn as_ref(&self) -> DirDescendant<&T, P> {
1574        DirDescendant::new(
1575            self.name.clone(),
1576            self.path.clone(),
1577            self.path_relative_to_ascendant.clone(),
1578            &self.value,
1579        )
1580    }
1581
1582    /// Clones the directory name and paths, but makes the value a mutable reference to the original value.
1583    ///
1584    /// # Examples
1585    ///
1586    /// ```
1587    /// use std::path::Path;
1588    /// use dir_structure::dir_descendants::DirDescendant;
1589    ///
1590    /// let mut descendant = DirDescendant::<_, Path>::new(
1591    ///     "child",
1592    ///     "root/a/b/child",
1593    ///     "a/b/child",
1594    ///     String::from("child_value"),
1595    /// );
1596    ///
1597    /// let mut mut_ref_descendant = descendant.as_mut();
1598    /// mut_ref_descendant.value_mut().push_str("_new");
1599    /// assert_eq!(descendant.value(), &String::from("child_value_new"));
1600    /// ```
1601    pub fn as_mut(&mut self) -> DirDescendant<&mut T, P> {
1602        DirDescendant::new(
1603            self.name.clone(),
1604            self.path.clone(),
1605            self.path_relative_to_ascendant.clone(),
1606            &mut self.value,
1607        )
1608    }
1609
1610    /// Maps the value of the directory descendant.
1611    ///
1612    /// # Examples
1613    ///
1614    /// ```
1615    /// use std::path::Path;
1616    /// use dir_structure::dir_descendants::DirDescendant;
1617    ///
1618    /// let descendant = DirDescendant::<_, Path>::new(
1619    ///     "child",
1620    ///     "root/a/b/child",
1621    ///     "a/b/child",
1622    ///     String::from("child_value"),
1623    /// );
1624    /// let mapped = descendant.map(|v| v.len());
1625    /// assert_eq!(mapped.value(), &11);
1626    /// ```
1627    pub fn map<F, U>(self, f: F) -> DirDescendant<U, P>
1628    where
1629        F: FnOnce(T) -> U,
1630    {
1631        DirDescendant::new(
1632            self.name,
1633            self.path,
1634            self.path_relative_to_ascendant,
1635            f(self.value),
1636        )
1637    }
1638}
1639
1640impl<T> Deref for DirDescendant<T> {
1641    type Target = T;
1642
1643    fn deref(&self) -> &Self::Target {
1644        &self.value
1645    }
1646}
1647
1648impl<T> DerefMut for DirDescendant<T> {
1649    fn deref_mut(&mut self) -> &mut Self::Target {
1650        &mut self.value
1651    }
1652}
1653
1654#[cfg(feature = "resolve-path")]
1655impl<T, F: FolderFilter + FolderRecurseFilter + FileFilter> DynamicHasField
1656    for DirDescendants<T, F>
1657{
1658    type Inner = T;
1659
1660    fn resolve_path<P: OwnedPathType>(mut p: P, name: &str) -> P {
1661        p.push_segment_str(name);
1662        p
1663    }
1664}