dir_structure/
dir_children.rs

1//! A structure representing the children of a directory.
2//!
3//! See [`DirChildren`] for more details.
4//!
5//! Additionally, [`ForceCreateDirChildren`] is a variant that forces the creation of the directory
6//! structure, even without any children.
7
8use std::fmt;
9use std::hash;
10use std::marker;
11use std::marker::PhantomData;
12use std::mem;
13use std::ops::Deref;
14use std::ops::DerefMut;
15use std::ops::RangeBounds;
16use std::path::Path;
17use std::pin::Pin;
18use std::slice;
19#[cfg(feature = "async")]
20use std::task::Context;
21#[cfg(feature = "async")]
22use std::task::Poll;
23use std::vec;
24
25#[cfg(feature = "async")]
26use futures::Stream;
27#[cfg(feature = "async")]
28use pin_project::pin_project;
29
30use crate::NoFilter;
31use crate::error::Error;
32use crate::error::VfsResult;
33use crate::prelude::*;
34#[cfg(feature = "async")]
35use crate::traits::asy::ReadFromAsync;
36#[cfg(feature = "async")]
37use crate::traits::async_vfs::VfsAsync;
38#[cfg(feature = "async")]
39use crate::traits::async_vfs::WriteSupportingVfsAsync;
40#[cfg(feature = "resolve-path")]
41use crate::traits::resolve::DynamicHasField;
42use crate::traits::sync::DirStructureItem;
43use crate::traits::vfs;
44use crate::traits::vfs::DirEntryInfo;
45use crate::traits::vfs::DirWalker as _;
46#[cfg(feature = "resolve-path")]
47use crate::traits::vfs::OwnedPathType;
48use crate::traits::vfs::PathType;
49#[cfg(feature = "async")]
50use crate::traits::vfs::VfsCore;
51
52/// A directory structure where we don't know the names of the folders at compile-time,
53/// and as such we cannot use the derive macro.
54///
55/// Instead we know that all the entries in the directory are folders,
56/// and that they all have the same structure inside (defined by the `T` type parameter),
57/// or they are all files (which can be read with [`DirChildren`]<[`String`]> for example).
58///
59/// In either case, [`ReadFrom::read_from`] must be able to read all the entries in
60/// the directory.
61///
62/// The [`WriteTo`] implementation will directly write the children to the directory it
63/// is passed, with no regards to the path stored in `self_path`.
64#[derive(PartialEq, Eq)]
65#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
66pub struct DirChildren<T, F: Filter<P> = NoFilter, P: PathType + ?Sized = Path> {
67    /// The children of the root directory.
68    pub children: Vec<DirChild<T, P>>,
69
70    #[cfg_attr(feature = "assert_eq", assert_eq(ignore))]
71    filter: marker::PhantomData<(F, P)>,
72}
73
74impl<T, P: PathType + ?Sized, F: Filter<P>> Clone for DirChildren<T, F, P>
75where
76    T: Clone,
77{
78    fn clone(&self) -> Self {
79        Self {
80            children: self.children.clone(),
81            filter: marker::PhantomData,
82        }
83    }
84}
85
86impl<T, P: PathType + ?Sized, F: Filter<P>> fmt::Debug for DirChildren<T, F, P>
87where
88    T: fmt::Debug,
89    P::PathSegmentOwned: fmt::Debug,
90{
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.debug_struct("DirChildren")
93            .field("children", &self.children)
94            .finish()
95    }
96}
97
98/// A filter for the children of a [`DirChildren`] structure.
99///
100/// This is used to filter out children that we don't want to
101/// read into the structure. For example, if we have a directory
102/// with a lot of files, we can use this to only read the
103/// files we want, for example, that have just a certain extension.
104///
105/// # Examples
106///
107/// For example, for a [`Filter`] that only allows `.txt` files:
108///
109#[cfg_attr(feature = "derive", doc = "```rust")]
110#[cfg_attr(not(feature = "derive"), doc = "```rust,compile_fail")]
111/// use std::path::Path;
112/// use std::path::PathBuf;
113///
114/// use dir_structure::{DirStructure, traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, Filter}};
115/// use dir_structure::prelude::*;
116///
117/// pub struct TextFileFilter;
118///
119/// impl Filter<Path> for TextFileFilter {
120///     fn allows(path: &Path) -> bool {
121///         path.extension()
122///             .and_then(|s| s.to_str())
123///             .map_or(false, |s| s == "txt")
124///     }
125/// }
126///
127/// fn main() -> Result<(), Box<dyn std::error::Error>> {
128///     let path = PathBuf::from("dir");
129///     #[derive(DirStructure)]
130///     struct Dir<Vfs: VfsCore<Path = Path>> {
131///        #[dir_structure(path = self)]
132///        text_files: DirChildren<String, TextFileFilter, Vfs::Path>,
133///     }
134///
135///     # std::fs::create_dir_all(&path)?;
136///
137///     std::fs::write(path.join("file1.txt"), "file1")?;
138///     std::fs::write(path.join("file2.txt"), "file2")?;
139///     std::fs::write(path.join("file3.bin"), "aaa")?;
140///
141///     let dir = Dir::read(&path)?;
142///     assert_eq!(dir.text_files.len(), 2);
143///     assert_eq!(dir.text_files.get_value_by_name("file1.txt"), Some(&String::from("file1")));
144///     assert_eq!(dir.text_files.get_value_by_name("file2.txt"), Some(&String::from("file2")));
145///     assert_eq!(dir.text_files.get_value_by_name("file3.bin"), None);
146///
147///     # std::fs::remove_dir_all(&path)?;
148///
149///     Ok(())
150/// }
151/// ```
152pub trait Filter<P: PathType + ?Sized> {
153    /// Checks if the path is allowed by this filter.
154    fn allows(path: &P) -> bool;
155}
156
157impl<P: PathType + ?Sized> Filter<P> for NoFilter {
158    fn allows(_path: &P) -> bool {
159        true
160    }
161}
162
163/// Creates a [`Filter`] type that only allows files / folders with a specific [extension](Path::extension).
164///
165/// # Examples
166///
167/// ```rust
168/// use std::path::Path;
169/// use dir_structure::dir_children::Filter;
170///
171/// dir_structure::ext_filter!(RustFile, "rs");
172///
173/// assert!(RustFile::allows(Path::new("main.rs")));
174/// assert!(RustFile::allows(Path::new("src/a/b/mod.rs")));
175/// assert!(!RustFile::allows(Path::new("main.txt")));
176/// ```
177#[macro_export]
178macro_rules! ext_filter {
179    ($vis:vis $name:ident, $Ext:literal) => {
180        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
181        $vis struct $name;
182
183        impl $crate::dir_children::Filter<::std::path::Path> for $name {
184            fn allows(path: &::std::path::Path) -> bool {
185                path.extension()
186                    .map_or(false, |s| s == $Ext)
187            }
188        }
189    };
190}
191
192/// Creates a [`Filter`] type that only allows files / folders with a specific [stem](Path::file_stem).
193///
194/// # Examples
195///
196/// ```rust
197/// use std::path::Path;
198/// use dir_structure::dir_children::Filter;
199///
200/// dir_structure::stem_filter!(MainFile, "main");
201///
202/// assert!(MainFile::allows(Path::new("main.rs")));
203/// assert!(MainFile::allows(Path::new("src/a/b/main.rs")));
204/// assert!(MainFile::allows(Path::new("main.txt")));
205/// assert!(!MainFile::allows(Path::new("main.a.rs")));
206/// ```
207#[macro_export]
208macro_rules! stem_filter {
209    ($vis:vis $name:ident, $base_name:literal) => {
210        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
211        $vis struct $name;
212
213        impl $crate::dir_children::Filter<::std::path::Path> for $name {
214            fn allows(path: &::std::path::Path) -> bool {
215                path.file_stem()
216                    .and_then(|s| s.to_str())
217                    .map_or(false, |s| s == $base_name)
218            }
219        }
220    };
221}
222
223/// Creates a [`Filter`] type that only allows files / folders with a specific [prefix](Path::file_prefix).
224///
225/// # Examples
226///
227/// ```rust
228/// use std::path::Path;
229/// use dir_structure::dir_children::Filter;
230///
231/// dir_structure::file_prefix_filter!(LogFile, "log");
232///
233/// assert!(LogFile::allows(Path::new("log.txt")));
234/// assert!(LogFile::allows(Path::new("log")));
235/// assert!(LogFile::allows(Path::new("log.log")));
236/// assert!(LogFile::allows(Path::new("src/a/b/log.txt")));
237/// assert!(!LogFile::allows(Path::new("src/a/b/file.txt")));
238/// ```
239#[macro_export]
240macro_rules! file_prefix_filter {
241    ($vis:vis $name:ident, $file_prefix:literal) => {
242        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
243        $vis struct $name;
244
245        impl $crate::dir_children::Filter<::std::path::Path> for $name {
246            fn allows(path: &::std::path::Path) -> bool {
247                path.file_prefix()
248                    .and_then(|s| s.to_str())
249                    .map_or(false, |s| s == $file_prefix)
250            }
251        }
252    };
253}
254
255impl<T, P: PathType + ?Sized, F: Filter<P>> Default for DirChildren<T, F, P> {
256    fn default() -> Self {
257        Self::new()
258    }
259}
260
261impl<T, F: Filter<P>, P: PathType + ?Sized> DirChildren<T, F, P> {
262    /// Creates an empty [`DirChildren`], with no children.
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use std::path::PathBuf;
268    /// use dir_structure::{dir_children::DirChildren, NoFilter};
269    ///
270    /// let d = DirChildren::<String, NoFilter>::new();
271    /// assert!(d.is_empty());
272    /// ```
273    pub fn new() -> Self {
274        Self {
275            children: Vec::new(),
276            filter: marker::PhantomData,
277        }
278    }
279
280    /// Creates a [`DirChildren`] with the given path and children.
281    ///
282    /// # Examples
283    ///
284    /// ```
285    /// use dir_structure::{dir_children::{DirChildren, DirChild}, NoFilter};
286    ///
287    /// let d = DirChildren::<String, NoFilter>::with_children_from_iter(
288    ///     vec![
289    ///         DirChild::new("file1.txt", "file1".to_owned()),
290    ///         DirChild::new("file2.txt", "file2".to_owned()),
291    ///     ],
292    /// );
293    /// assert!(!d.is_empty());
294    /// ```
295    pub fn with_children_from_iter(children: impl IntoIterator<Item = DirChild<T, P>>) -> Self {
296        Self {
297            children: children.into_iter().collect(),
298            filter: marker::PhantomData,
299        }
300    }
301
302    /// Maps the children of this [`DirChildren`] to a new type.
303    ///
304    /// This is useful for converting the children to a different type,
305    /// for example, if you want to convert the children to a different
306    /// type of [`DirStructureItem`].
307    ///
308    /// This is a convenience method that allows you to use the
309    /// `map` method on the children of this [`DirChildren`].
310    ///
311    /// # Examples
312    ///
313    /// ```rust
314    /// use std::path::Path;
315    /// use std::pin::Pin;
316    /// use dir_structure::{dir_children::{DirChildren, DirChild}, prelude::*};
317    ///
318    /// #[derive(Debug, PartialEq, Eq)]
319    /// struct NewType(String);
320    ///
321    /// let dir = DirChildren::<_, dir_structure::NoFilter>::with_children_from_iter(
322    ///     vec![
323    ///         DirChild::new("file1.txt", "file1".to_owned()),
324    ///         DirChild::new("file2.txt", "file2".to_owned()),
325    ///         DirChild::new("file3.txt", "file3".to_owned()),
326    ///     ],
327    /// );
328    /// let dir = dir.map::<_, _, dir_structure::NoFilter, Path>(|child| child.map_value(NewType));
329    /// assert_eq!(
330    ///     dir,
331    ///     DirChildren::with_children_from_iter(
332    ///         vec![
333    ///             DirChild::new("file1.txt", NewType("file1".to_owned())),
334    ///             DirChild::new("file2.txt", NewType("file2".to_owned())),
335    ///             DirChild::new("file3.txt", NewType("file3".to_owned())),
336    ///         ],
337    ///     )
338    /// );
339    /// ```
340    pub fn map<U, MapF, F2, P2>(self, f: MapF) -> DirChildren<U, F2, P2>
341    where
342        MapF: FnMut(DirChild<T, P>) -> DirChild<U, P2>,
343        F2: Filter<P2>,
344        P2: PathType + ?Sized,
345    {
346        let children = self.children.into_iter().map(f).collect();
347        DirChildren {
348            children,
349            filter: marker::PhantomData,
350        }
351    }
352
353    /// Maps the filter type. The children remain unchanged.
354    ///
355    /// This is useful if you are trying to pass a DirChildren<T, F1> to
356    /// a function requiring a DirChildren<T, F2>, where F1 and F2 are two
357    /// distinct types implementing [`Filter`].
358    ///
359    /// # Examples
360    ///
361    /// ```rust
362    /// use std::path::Path;
363    /// use dir_structure::traits::vfs::PathType;
364    /// use dir_structure::dir_children::{Filter, DirChildren};
365    ///
366    /// struct NewFilter;
367    ///
368    /// impl<P: PathType + ?Sized> Filter<P> for NewFilter {
369    ///     fn allows(_path: &P) -> bool {
370    ///         true
371    ///     }
372    /// }
373    ///
374    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
375    /// let d2: DirChildren<String, NewFilter> = d.map_filter::<NewFilter>();
376    /// ```
377    pub fn map_filter<NewF>(self) -> DirChildren<T, NewF, P>
378    where
379        NewF: Filter<P>,
380    {
381        DirChildren {
382            children: self.children,
383            filter: marker::PhantomData,
384        }
385    }
386
387    /// Returns the number of children.
388    ///
389    /// # Examples
390    ///
391    /// ```rust
392    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
393    ///
394    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
395    /// assert_eq!(d.len(), 0);
396    ///
397    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
398    ///     vec![
399    ///         DirChild::new("file1.txt", "file1".to_owned()),
400    ///         DirChild::new("file2.txt", "file2".to_owned()),
401    ///     ],
402    /// );
403    /// assert_eq!(d.len(), 2);
404    /// ```
405    pub fn len(&self) -> usize {
406        self.children.len()
407    }
408
409    /// Returns true if there are no children.
410    ///
411    /// # Examples
412    ///
413    /// ```
414    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
415    ///
416    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
417    /// assert!(d.is_empty());
418    ///
419    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
420    ///     vec![
421    ///         DirChild::new("file1.txt", "file1".to_owned()),
422    ///         DirChild::new("file2.txt", "file2".to_owned()),
423    ///     ],
424    /// );
425    /// assert!(!d.is_empty());
426    /// ```
427    pub fn is_empty(&self) -> bool {
428        self.children.is_empty()
429    }
430
431    /// Gets the child at the specified index.
432    ///
433    /// # Examples
434    ///
435    /// ```rust
436    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
437    ///
438    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
439    /// assert_eq!(d.get(0), None);
440    /// assert_eq!(d.get(1), None);
441    /// assert_eq!(d.get(100), None);
442    ///
443    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
444    ///     vec![
445    ///         DirChild::new("file1.txt", "file1".to_owned()),
446    ///         DirChild::new("file2.txt", "file2".to_owned()),
447    ///     ],
448    /// );
449    /// assert_eq!(d.get(0), Some(&DirChild::new("file1.txt", "file1".to_owned())));
450    /// assert_eq!(d.get(1), Some(&DirChild::new("file2.txt", "file2".to_owned())));
451    /// assert_eq!(d.get(2), None);
452    /// assert_eq!(d.get(100), None);
453    /// ```
454    pub fn get(&self, index: usize) -> Option<&DirChild<T, P>> {
455        self.children.get(index)
456    }
457
458    /// Gets a mutable reference to the child at the specified index.
459    /// This is a mutable version of [`get`][Self::get].
460    ///
461    /// # Examples
462    ///
463    /// ```rust
464    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
465    ///
466    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::new();
467    /// assert_eq!(d.get_mut(0), None);
468    /// assert_eq!(d.get_mut(1), None);
469    /// assert_eq!(d.get_mut(100), None);
470    ///
471    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
472    ///     vec![
473    ///         DirChild::new("file1.txt", "file1".to_owned()),
474    ///         DirChild::new("file2.txt", "file2".to_owned()),
475    ///     ],
476    /// );
477    /// assert_eq!(d.get_mut(0), Some(&mut DirChild::new("file1.txt", "file1".to_owned())));
478    /// assert_eq!(d.get_mut(1), Some(&mut DirChild::new("file2.txt", "file2".to_owned())));
479    /// assert_eq!(d.get_mut(2), None);
480    /// assert_eq!(d.get_mut(100), None);
481    /// ```
482    pub fn get_mut(&mut self, index: usize) -> Option<&mut DirChild<T, P>> {
483        self.children.get_mut(index)
484    }
485
486    /// Gets the child with the specified "file" name (last segment of path).
487    ///
488    /// # Examples
489    ///
490    /// ```rust
491    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
492    ///
493    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
494    /// assert_eq!(d.get_name(""), None);
495    /// assert_eq!(d.get_name("any_name"), None);
496    /// assert_eq!(d.get_name("aaaa"), None);
497    ///
498    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
499    ///     vec![
500    ///         DirChild::new("file1.txt", "file1".to_owned()),
501    ///         DirChild::new("file2.txt", "file2".to_owned()),
502    ///     ],
503    /// );
504    /// assert_eq!(d.get_name("file1.txt"), Some(&DirChild::new("file1.txt", "file1".to_owned())));
505    /// assert_eq!(d.get_name("file2.txt"), Some(&DirChild::new("file2.txt", "file2".to_owned())));
506    /// assert_eq!(d.get_name("any_name"), None);
507    /// assert_eq!(d.get_name("aaaa"), None);
508    /// ```
509    pub fn get_name(&self, name: impl AsRef<P::PathSegmentRef>) -> Option<&DirChild<T, P>>
510    where
511        P::PathSegmentRef: PartialEq,
512    {
513        self.children
514            .iter()
515            .find(|child| child.file_name.as_ref() == name.as_ref())
516    }
517
518    /// Gets the child with the specified "file" name (last segment of path).
519    /// This is a mutable version of [`get_name`][Self::get_name].
520    ///
521    /// # Examples
522    ///
523    /// ```rust
524    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
525    ///
526    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::new();
527    /// assert_eq!(d.get_name_mut(""), None);
528    /// assert_eq!(d.get_name_mut("any_name"), None);
529    /// assert_eq!(d.get_name_mut("aaaa"), None);
530    ///
531    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
532    ///     vec![
533    ///         DirChild::new("file1.txt", "file1".to_owned()),
534    ///         DirChild::new("file2.txt", "file2".to_owned()),
535    ///     ],
536    /// );
537    /// assert_eq!(d.get_name_mut("file1.txt"), Some(&mut DirChild::new("file1.txt", "file1".to_owned())));
538    /// assert_eq!(d.get_name_mut("file2.txt"), Some(&mut DirChild::new("file2.txt", "file2".to_owned())));
539    /// assert_eq!(d.get_name_mut("any_name"), None);
540    /// assert_eq!(d.get_name_mut("aaaa"), None);
541    /// ```
542    pub fn get_name_mut(
543        &mut self,
544        name: impl AsRef<P::PathSegmentRef>,
545    ) -> Option<&mut DirChild<T, P>>
546    where
547        P::PathSegmentRef: PartialEq,
548    {
549        self.children
550            .iter_mut()
551            .find(|child| child.file_name.as_ref() == name.as_ref())
552    }
553
554    /// Gets the value of the child with the specified "file" name (last segment of path).
555    ///
556    /// # Examples
557    ///
558    /// ```rust
559    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
560    ///
561    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
562    /// assert_eq!(d.get_value_by_name(""), None);
563    /// assert_eq!(d.get_value_by_name("any_name"), None);
564    /// assert_eq!(d.get_value_by_name("aaaa"), None);
565    ///
566    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
567    ///     vec![
568    ///         DirChild::new("file1.txt", "file1".to_owned()),
569    ///         DirChild::new("file2.txt", "file2".to_owned()),
570    ///     ],
571    /// );
572    /// assert_eq!(d.get_value_by_name("file1.txt"), Some(&"file1".to_owned()));
573    /// assert_eq!(d.get_value_by_name("file2.txt"), Some(&"file2".to_owned()));
574    /// assert_eq!(d.get_value_by_name("any_name"), None);
575    /// assert_eq!(d.get_value_by_name("aaaa"), None);
576    /// ```
577    pub fn get_value_by_name(&self, name: impl AsRef<P::PathSegmentRef>) -> Option<&T>
578    where
579        P::PathSegmentRef: PartialEq,
580    {
581        self.get_name(name).map(|child| &child.value)
582    }
583
584    /// Gets the value of the child with the specified "file" name (last segment of path).
585    /// This is a mutable version of [`get_value_by_name`][Self::get_value_by_name].
586    ///
587    /// # Examples
588    ///
589    /// ```rust
590    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
591    ///
592    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::new();
593    /// assert_eq!(d.get_value_by_name_mut(""), None);
594    /// assert_eq!(d.get_value_by_name_mut("any_name"), None);
595    /// assert_eq!(d.get_value_by_name_mut("aaaa"), None);
596    ///
597    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
598    ///     vec![
599    ///         DirChild::new("file1.txt", "file1".to_owned()),
600    ///         DirChild::new("file2.txt", "file2".to_owned()),
601    ///     ],
602    /// );
603    /// assert_eq!(d.get_value_by_name_mut("file1.txt"), Some(&mut "file1".to_owned()));
604    /// assert_eq!(d.get_value_by_name_mut("file2.txt"), Some(&mut "file2".to_owned()));
605    /// assert_eq!(d.get_value_by_name_mut("any_name"), None);
606    /// assert_eq!(d.get_value_by_name_mut("aaaa"), None);
607    /// ```
608    pub fn get_value_by_name_mut(&mut self, name: impl AsRef<P::PathSegmentRef>) -> Option<&mut T>
609    where
610        P::PathSegmentRef: PartialEq,
611    {
612        self.get_name_mut(name).map(|child| &mut child.value)
613    }
614
615    /// Returns an iterator over the children.
616    ///
617    /// # Examples
618    ///
619    /// ```rust
620    /// use std::path::{Path, PathBuf};
621    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
622    ///
623    /// let d = DirChildren::<String, dir_structure::NoFilter>::new();
624    /// let mut i = d.iter();
625    /// assert_eq!(i.next(), None);
626    ///
627    /// let d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
628    ///     vec![
629    ///         DirChild::new("file1.txt", "file1".to_owned()),
630    ///         DirChild::new("file2.txt", "file2".to_owned()),
631    ///     ],
632    /// );
633    /// let mut i = d.iter();
634    /// assert_eq!(i.next(), Some(&DirChild::new("file1.txt", "file1".to_owned())));
635    /// assert_eq!(i.next(), Some(&DirChild::new("file2.txt", "file2".to_owned())));
636    /// assert_eq!(i.next(), None);
637    /// ```
638    pub fn iter(&self) -> DirChildrenIter<'_, T, P> {
639        DirChildrenIter(self.children.iter())
640    }
641
642    /// Returns a mutable iterator over the children.
643    ///
644    /// # Examples
645    ///
646    /// ```rust
647    /// use std::path::{Path, PathBuf};
648    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
649    ///
650    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
651    ///     vec![
652    ///         DirChild::new("file1.txt", "file1".to_owned()),
653    ///         DirChild::new("file2.txt", "file2".to_owned()),
654    ///     ],
655    /// );
656    /// let mut i = d.iter_mut();
657    /// assert_eq!(i.next(), Some(&mut DirChild::new("file1.txt", "file1".to_owned())));
658    /// assert_eq!(i.next(), Some(&mut DirChild::new("file2.txt", "file2".to_owned())));
659    /// assert_eq!(i.next(), None);
660    /// ```
661    ///
662    /// Modifying the children is also possible:
663    ///
664    /// ```rust
665    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
666    ///
667    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
668    ///     vec![
669    ///         DirChild::new("file1.txt", "file1".to_owned()),
670    ///         DirChild::new("file2.txt", "file2".to_owned()),
671    ///     ],
672    /// );
673    /// d.iter_mut().for_each(|child| *child.value_mut() = "modified".to_owned());
674    /// let mut i = d.iter();
675    /// assert_eq!(i.next(), Some(&DirChild::new("file1.txt", "modified".to_owned())));
676    /// assert_eq!(i.next(), Some(&DirChild::new("file2.txt", "modified".to_owned())));
677    /// assert_eq!(i.next(), None);
678    /// ```
679    pub fn iter_mut(&mut self) -> DirChildrenIterMut<'_, T, P> {
680        DirChildrenIterMut(self.children.iter_mut())
681    }
682
683    /// Pushes a new child to the end of the children list.
684    ///
685    /// This method takes a file name and a value, and creates a new `DirChild`
686    /// with the given file name and value, then pushes it to the end of the children
687    /// list.
688    ///
689    /// # Examples
690    ///
691    /// ```rust
692    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
693    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::new();
694    ///
695    /// d.push("file1.txt", "file1".to_owned());
696    ///
697    /// let mut i = d.iter();
698    /// assert_eq!(i.next(), Some(&DirChild::new("file1.txt", "file1".to_owned())));
699    /// assert_eq!(i.next(), None);
700    ///
701    /// d.push("file2.txt", "file2".to_owned());
702    ///
703    /// let mut i = d.iter();
704    /// assert_eq!(i.next(), Some(&DirChild::new("file1.txt", "file1".to_owned())));
705    /// assert_eq!(i.next(), Some(&DirChild::new("file2.txt", "file2".to_owned())));
706    /// assert_eq!(i.next(), None);
707    /// ```
708    pub fn push(&mut self, file_name: impl Into<P::PathSegmentOwned>, value: T) {
709        self.children.push(DirChild {
710            file_name: file_name.into(),
711            value,
712        });
713    }
714
715    /// Retains only the children specified by the predicate.
716    ///
717    /// The predicate is a closure that takes a reference to a `DirChild<T>`
718    /// and returns `true` if the child should be kept, or `false` if it should be removed.
719    ///
720    /// # Examples
721    ///
722    /// ```rust
723    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
724    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
725    ///     vec![
726    ///         DirChild::new("file1.txt", "file1".to_owned()),
727    ///         DirChild::new("file2.txt", "file2".to_owned()),
728    ///     ],
729    /// );
730    /// d.retain(|child| child.file_name() != "file1.txt");
731    /// let mut i = d.iter();
732    /// assert_eq!(i.next(), Some(&DirChild::new("file2.txt", "file2".to_owned())));
733    /// assert_eq!(i.next(), None);
734    /// ```
735    pub fn retain(&mut self, f: impl FnMut(&DirChild<T, P>) -> bool) {
736        self.children.retain(f);
737    }
738
739    /// Drains the children in the specified range, returning an iterator over the removed children.
740    /// The range is specified using the standard Rust range syntax.
741    ///
742    /// # Examples
743    ///
744    /// ```rust
745    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
746    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
747    ///     vec![
748    ///         DirChild::new("file1.txt", "file1".to_owned()),
749    ///         DirChild::new("file2.txt", "file2".to_owned()),
750    ///         DirChild::new("file3.txt", "file3".to_owned()),
751    ///     ],
752    /// );
753    /// let drained: Vec<_> = d.drain(0..1).collect();
754    /// assert_eq!(drained, vec![DirChild::new("file1.txt", "file1".to_owned())]);
755    /// let mut i = d.iter();
756    /// assert_eq!(i.next(), Some(&DirChild::new("file2.txt", "file2".to_owned())));
757    /// assert_eq!(i.next(), Some(&DirChild::new("file3.txt", "file3".to_owned())));
758    /// assert_eq!(i.next(), None);
759    /// ```
760    pub fn drain(&mut self, range: impl RangeBounds<usize>) -> DirChildrenDrain<'_, T, P> {
761        DirChildrenDrain(self.children.drain(range))
762    }
763
764    /// Extracts the children in the specified range that satisfy the given predicate,
765    /// returning an iterator over the removed children.
766    ///
767    /// The range is specified using the standard Rust range syntax.
768    /// The predicate is a closure that takes a mutable reference to a `DirChild<T>`
769    /// and returns `true` if the child should be removed, or `false` if it should be kept.
770    ///
771    /// # Examples
772    ///
773    /// ```rust
774    /// use dir_structure::{traits::sync::{DirStructure, DirStructureItem}, dir_children::{DirChildren, DirChild}};
775    /// let mut d = DirChildren::<String, dir_structure::NoFilter>::with_children_from_iter(
776    ///     vec![
777    ///         DirChild::new("file1.txt", "file1".to_owned()),
778    ///         DirChild::new("file2.txt", "file2".to_owned()),
779    ///         DirChild::new("file3.txt", "file3".to_owned()),
780    ///         DirChild::new("file4.txt", "file4".to_owned()),
781    ///     ],
782    /// );
783    /// let extracted: Vec<_> = d.extract_if(1..3, |child| child.file_name() == "file2.txt").collect();
784    /// assert_eq!(extracted, vec![DirChild::new("file2.txt", "file2".to_owned())]);
785    ///
786    /// let mut i = d.iter();
787    /// assert_eq!(i.next(), Some(&DirChild::new("file1.txt", "file1".to_owned())));
788    /// assert_eq!(i.next(), Some(&DirChild::new("file3.txt", "file3".to_owned())));
789    /// assert_eq!(i.next(), Some(&DirChild::new("file4.txt", "file4".to_owned())));
790    /// assert_eq!(i.next(), None);
791    /// ```
792    pub fn extract_if<'a, Fi>(
793        &'a mut self,
794        range: impl RangeBounds<usize>,
795        filter: Fi,
796    ) -> DirChildrenExtractIf<'a, T, P, Fi>
797    where
798        Fi: FnMut(&mut DirChild<T, P>) -> bool,
799    {
800        DirChildrenExtractIf(self.children.extract_if(range, filter))
801    }
802}
803
804impl<T, P: PathType + ?Sized, F> From<Vec<DirChild<T, P>>> for DirChildren<T, F, P>
805where
806    F: Filter<P>,
807{
808    fn from(children: Vec<DirChild<T, P>>) -> Self {
809        Self {
810            children,
811            filter: marker::PhantomData,
812        }
813    }
814}
815
816impl<T, P: PathType + ?Sized, F> Extend<DirChild<T, P>> for DirChildren<T, F, P>
817where
818    F: Filter<P>,
819{
820    fn extend<I: IntoIterator<Item = DirChild<T, P>>>(&mut self, iter: I) {
821        self.children.extend(iter);
822    }
823}
824
825impl<T, P: PathType + ?Sized, F> FromIterator<DirChild<T, P>> for DirChildren<T, F, P>
826where
827    F: Filter<P>,
828{
829    fn from_iter<I: IntoIterator<Item = DirChild<T, P>>>(iter: I) -> Self {
830        Self::with_children_from_iter(iter)
831    }
832}
833
834/// An iterator that drains the children of a [`DirChildren`].
835///
836/// See [`DirChildren::drain`].
837pub struct DirChildrenDrain<'a, T, P: PathType + ?Sized>(vec::Drain<'a, DirChild<T, P>>);
838
839impl<T, P: PathType + ?Sized> Iterator for DirChildrenDrain<'_, T, P> {
840    type Item = DirChild<T, P>;
841
842    fn next(&mut self) -> Option<Self::Item> {
843        self.0.next()
844    }
845
846    fn size_hint(&self) -> (usize, Option<usize>) {
847        self.0.size_hint()
848    }
849}
850
851impl<T, P: PathType + ?Sized> ExactSizeIterator for DirChildrenDrain<'_, T, P> {
852    fn len(&self) -> usize {
853        self.0.len()
854    }
855}
856
857impl<T, P: PathType + ?Sized> DoubleEndedIterator for DirChildrenDrain<'_, T, P> {
858    fn next_back(&mut self) -> Option<Self::Item> {
859        self.0.next_back()
860    }
861}
862
863impl<'a, T, P: PathType + ?Sized + 'a, F: Filter<P>, Vfs: vfs::Vfs<'a, Path = P>> ReadFrom<'a, Vfs>
864    for DirChildren<T, F, P>
865where
866    T: ReadFrom<'a, Vfs>,
867    F: 'a,
868{
869    fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
870    where
871        Self: Sized,
872    {
873        let mut children = Vec::new();
874        let mut walker = vfs.walk_dir(path)?;
875        while let Some(child) = walker.next() {
876            let DirEntryInfo {
877                name,
878                path: child_path,
879                ..
880            } = child?;
881
882            if !F::allows(child_path.as_ref()) {
883                continue;
884            }
885
886            let value = T::read_from(child_path.as_ref(), vfs)?;
887            children.push(DirChild {
888                file_name: name,
889                value,
890            });
891        }
892
893        Ok(DirChildren {
894            children,
895            filter: marker::PhantomData,
896        })
897    }
898}
899
900#[cfg(feature = "async")]
901#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
902#[pin_project(project_replace = DirChildrenReadAsyncFutureProjOwn)]
903#[doc(hidden)]
904pub enum DirChildrenReadAsyncFuture<'a, T, F, Vfs: VfsAsync + 'a>
905where
906    T: ReadFromAsync<'a, Vfs> + 'static,
907    F: Filter<Vfs::Path> + Send + 'static,
908    T::Future: Future<Output = VfsResult<T, Vfs>> + Send + Unpin + 'a,
909{
910    Poison,
911    Init(
912        Pin<Box<Vfs::DirWalkFuture<'a>>>,
913        Vec<DirChild<T, Vfs::Path>>,
914        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
915        Pin<&'a Vfs>,
916        PhantomData<F>,
917    ),
918    Begin(
919        Pin<Box<Vfs::DirWalk<'a>>>,
920        Vec<DirChild<T, Vfs::Path>>,
921        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
922        Pin<&'a Vfs>,
923    ),
924    ReadAsync(
925        Pin<Box<Vfs::DirWalk<'a>>>,
926        Vec<DirChild<T, Vfs::Path>>,
927        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
928        T::Future,
929        <Vfs::Path as PathType>::PathSegmentOwned,
930        Pin<&'a Vfs>,
931    ),
932}
933
934#[cfg(feature = "async")]
935#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
936impl<'a, T, F, Vfs: VfsAsync + 'a> Future for DirChildrenReadAsyncFuture<'a, T, F, Vfs>
937where
938    T: ReadFromAsync<'a, Vfs> + Send + 'static,
939    F: Filter<Vfs::Path> + Send + 'static,
940    T::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'static,
941{
942    type Output = VfsResult<DirChildren<T, F, Vfs::Path>, Vfs>;
943
944    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
945        let this = self.as_mut().project_replace(Self::Poison);
946
947        match this {
948            DirChildrenReadAsyncFutureProjOwn::Init(mut entries, children, path, vfs, _) => {
949                match entries.as_mut().poll(cx) {
950                    Poll::Ready(Ok(entries)) => {
951                        self.project_replace(DirChildrenReadAsyncFuture::Begin(
952                            Box::pin(entries),
953                            children,
954                            path,
955                            vfs,
956                        ));
957                        cx.waker().wake_by_ref();
958                        Poll::Pending
959                    }
960                    Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
961                    Poll::Pending => {
962                        self.project_replace(DirChildrenReadAsyncFuture::Init(
963                            entries,
964                            children,
965                            path,
966                            vfs,
967                            PhantomData::<F>,
968                        ));
969                        Poll::Pending
970                    }
971                }
972            }
973            DirChildrenReadAsyncFutureProjOwn::Begin(mut entries, children, path, vfs) => {
974                use std::task::Poll;
975
976                match entries.as_mut().poll_next(cx) {
977                    Poll::Ready(Some(Ok(DirEntryInfo {
978                        name,
979                        path: path_child,
980                        kind: _,
981                    }))) => {
982                        if !F::allows(path_child.as_ref()) {
983                            self.project_replace(DirChildrenReadAsyncFuture::Begin(
984                                entries, children, path, vfs,
985                            ));
986                            cx.waker().wake_by_ref();
987                            return Poll::Pending;
988                        }
989
990                        let value_future = T::read_from_async(path_child, vfs);
991                        self.project_replace(DirChildrenReadAsyncFuture::ReadAsync(
992                            entries,
993                            children,
994                            path,
995                            value_future,
996                            name,
997                            vfs,
998                        ));
999                        cx.waker().wake_by_ref();
1000                        Poll::Pending
1001                    }
1002                    Poll::Ready(None) => Poll::Ready(Ok(DirChildren {
1003                        children,
1004                        filter: marker::PhantomData,
1005                    })),
1006                    Poll::Ready(Some(Err(e))) => Poll::Ready(Err(e)),
1007                    Poll::Pending => {
1008                        self.project_replace(DirChildrenReadAsyncFuture::Begin(
1009                            entries, children, path, vfs,
1010                        ));
1011                        Poll::Pending
1012                    }
1013                }
1014            }
1015            DirChildrenReadAsyncFutureProjOwn::ReadAsync(
1016                entries,
1017                mut children,
1018                path,
1019                mut value_fut,
1020                file_name,
1021                vfs,
1022            ) => match Pin::<&mut T::Future>::new(&mut value_fut).poll(cx) {
1023                Poll::Ready(Ok(value)) => {
1024                    children.push(DirChild { file_name, value });
1025                    self.project_replace(DirChildrenReadAsyncFuture::Begin(
1026                        entries, children, path, vfs,
1027                    ));
1028                    cx.waker().wake_by_ref();
1029                    Poll::Pending
1030                }
1031                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
1032                Poll::Pending => {
1033                    self.project_replace(DirChildrenReadAsyncFuture::ReadAsync(
1034                        entries,
1035                        children,
1036                        path,
1037                        value_fut,
1038                        file_name.clone(),
1039                        vfs,
1040                    ));
1041                    Poll::Pending
1042                }
1043            },
1044            DirChildrenReadAsyncFutureProjOwn::Poison => {
1045                panic!("DirChildrenReadAsyncFuture is poisoned, this should never happen");
1046            }
1047        }
1048    }
1049}
1050
1051#[cfg(feature = "async")]
1052#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1053impl<'a, T, F, Vfs: VfsAsync + 'a> ReadFromAsync<'a, Vfs> for DirChildren<T, F, Vfs::Path>
1054where
1055    T: ReadFromAsync<'a, Vfs> + Send + 'static,
1056    F: Filter<Vfs::Path> + Send + 'static,
1057    T::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'static,
1058{
1059    type Future = DirChildrenReadAsyncFuture<'a, T, F, Vfs>;
1060
1061    fn read_from_async(
1062        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1063        vfs: Pin<&'a Vfs>,
1064    ) -> Self::Future {
1065        let f = Box::pin(vfs.walk_dir(path.clone()));
1066        DirChildrenReadAsyncFuture::Init(f, Vec::new(), path, vfs, PhantomData::<F>)
1067    }
1068}
1069
1070impl<'a, T, F, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for DirChildren<T, F, Vfs::Path>
1071where
1072    T: WriteTo<'a, Vfs>,
1073    F: Filter<Vfs::Path>,
1074{
1075    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
1076        for child in &self.children {
1077            let child_path = path.join_segment(&child.file_name);
1078            child.value.write_to(child_path.as_ref(), vfs)?;
1079        }
1080
1081        Ok(())
1082    }
1083}
1084
1085#[cfg(feature = "async")]
1086#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1087impl<'a, T, F, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs>
1088    for DirChildren<T, F, Vfs::Path>
1089where
1090    T: WriteToAsync<'a, Vfs> + Send + Sync + 'static,
1091    F: Filter<Vfs::Path> + Send + 'static,
1092    T::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'a,
1093{
1094    type Future = DirChildrenWriteAsyncFuture<'a, T, Vfs>;
1095
1096    fn write_to_async(
1097        self,
1098        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1099        vfs: Pin<&'a Vfs>,
1100    ) -> Self::Future {
1101        DirChildrenWriteAsyncFuture::Init(self.into_iter(), path, vfs)
1102    }
1103}
1104
1105#[cfg(feature = "async")]
1106#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1107#[pin_project(project_replace = DirChildrenWriteAsyncFutureProjOwn)]
1108#[doc(hidden)]
1109pub enum DirChildrenWriteAsyncFuture<'a, T, Vfs: WriteSupportingVfsAsync + 'static>
1110where
1111    T: WriteToAsync<'a, Vfs>,
1112    <T as WriteToAsync<'a, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin,
1113{
1114    Poison,
1115    Init(
1116        DirChildrenIntoIter<T, <Vfs as VfsCore>::Path>,
1117        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1118        Pin<&'a Vfs>,
1119    ),
1120    Write(
1121        DirChildrenIntoIter<T, <Vfs as VfsCore>::Path>,
1122        <T as WriteToAsync<'a, Vfs>>::Future,
1123        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1124        Pin<&'a Vfs>,
1125    ),
1126}
1127
1128#[cfg(feature = "async")]
1129#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1130impl<'a, T, Vfs: WriteSupportingVfsAsync + 'static> Future
1131    for DirChildrenWriteAsyncFuture<'a, T, Vfs>
1132where
1133    T: WriteToAsync<'a, Vfs>,
1134    <T as WriteToAsync<'a, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin,
1135{
1136    type Output = VfsResult<(), Vfs>;
1137
1138    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1139        let this = self.as_mut().project_replace(Self::Poison);
1140
1141        match this {
1142            DirChildrenWriteAsyncFutureProjOwn::Init(mut iter, path, vfs) => {
1143                if let Some(child) = iter.next() {
1144                    let fut = child
1145                        .value
1146                        .write_to_async(path.as_ref().join_segment(&child.file_name), vfs);
1147                    self.project_replace(Self::Write(iter, fut, path.clone(), vfs));
1148                    cx.waker().wake_by_ref();
1149                    Poll::Pending
1150                } else {
1151                    Poll::Ready(Ok(()))
1152                }
1153            }
1154            DirChildrenWriteAsyncFutureProjOwn::Write(mut iter, mut fut, path, vfs) => {
1155                match Pin::new(&mut fut).poll(cx) {
1156                    Poll::Ready(Ok(())) => {
1157                        if let Some(child) = iter.next() {
1158                            let new_fut = child
1159                                .value
1160                                .write_to_async(path.as_ref().join_segment(&child.file_name), vfs);
1161                            self.project_replace(Self::Write(iter, new_fut, path.clone(), vfs));
1162                            cx.waker().wake_by_ref();
1163                            Poll::Pending
1164                        } else {
1165                            Poll::Ready(Ok(()))
1166                        }
1167                    }
1168                    Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
1169                    Poll::Pending => {
1170                        self.project_replace(Self::Write(iter, fut, path.clone(), vfs));
1171                        Poll::Pending
1172                    }
1173                }
1174            }
1175            DirChildrenWriteAsyncFutureProjOwn::Poison => {
1176                panic!("DirChildrenWriteAsyncFuture is poisoned, this should never happen");
1177            }
1178        }
1179    }
1180}
1181
1182#[cfg(feature = "async")]
1183#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1184impl<'r, T, F, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsyncRef<'r, Vfs>
1185    for DirChildren<T, F, Vfs::Path>
1186where
1187    T: WriteToAsyncRef<'r, Vfs> + Send + Sync + 'static,
1188    F: Filter<Vfs::Path> + Send + 'static,
1189    for<'f> <T as WriteToAsyncRef<'r, Vfs>>::Future<'f>:
1190        Future<Output = VfsResult<(), Vfs>> + Unpin + 'f,
1191{
1192    type Future<'a>
1193        = DirChildrenWriteAsyncRefFuture<'r, 'a, T, Vfs>
1194    where
1195        T: 'a,
1196        Vfs: 'a,
1197        Self: 'a,
1198        'r: 'a;
1199
1200    fn write_to_async_ref<'a>(
1201        &'a self,
1202        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1203        vfs: Pin<&'a Vfs>,
1204    ) -> <Self as WriteToAsyncRef<'r, Vfs>>::Future<'a>
1205    where
1206        'r: 'a,
1207    {
1208        DirChildrenWriteAsyncRefFuture::Init(self.iter(), path, vfs)
1209    }
1210}
1211
1212#[cfg(feature = "async")]
1213#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1214#[pin_project(project_replace = DirChildrenWriteAsyncRefFutureProjOwn)]
1215#[doc(hidden)]
1216pub enum DirChildrenWriteAsyncRefFuture<'r, 'f, T, Vfs: WriteSupportingVfsAsync + 'static>
1217where
1218    T: WriteToAsyncRef<'r, Vfs> + 'r,
1219    <T as WriteToAsyncRef<'r, Vfs>>::Future<'f>: Future<Output = VfsResult<(), Vfs>> + Unpin + 'f,
1220    'r: 'f,
1221{
1222    Poison,
1223    Init(
1224        DirChildrenIter<'f, T, Vfs::Path>,
1225        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1226        Pin<&'f Vfs>,
1227    ),
1228    Write(
1229        DirChildrenIter<'f, T, Vfs::Path>,
1230        <T as WriteToAsyncRef<'r, Vfs>>::Future<'f>,
1231        <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
1232        Pin<&'f Vfs>,
1233    ),
1234}
1235
1236#[cfg(feature = "async")]
1237#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1238impl<'r, 'f, T, Vfs: WriteSupportingVfsAsync + 'static> Future
1239    for DirChildrenWriteAsyncRefFuture<'r, 'f, T, Vfs>
1240where
1241    T: WriteToAsyncRef<'r, Vfs>,
1242    <T as WriteToAsyncRef<'r, Vfs>>::Future<'f>: Future<Output = VfsResult<(), Vfs>> + Unpin + 'f,
1243    'r: 'f,
1244{
1245    type Output = VfsResult<(), Vfs>;
1246
1247    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1248        let this = self.as_mut().project_replace(Self::Poison);
1249
1250        match this {
1251            DirChildrenWriteAsyncRefFutureProjOwn::Init(mut iter, path, vfs) => {
1252                if let Some(child) = iter.next() {
1253                    let fut = child
1254                        .value
1255                        .write_to_async_ref(path.as_ref().join_segment(&child.file_name), vfs);
1256                    self.project_replace(Self::Write(iter, fut, path.clone(), vfs));
1257                    cx.waker().wake_by_ref();
1258                    Poll::Pending
1259                } else {
1260                    Poll::Ready(Ok(()))
1261                }
1262            }
1263            DirChildrenWriteAsyncRefFutureProjOwn::Write(mut iter, mut fut, path, vfs) => {
1264                match Pin::new(&mut fut).poll(cx) {
1265                    Poll::Ready(Ok(())) => {
1266                        if let Some(child) = iter.next() {
1267                            let new_fut = child.value.write_to_async_ref(
1268                                path.as_ref().join_segment(&child.file_name),
1269                                vfs,
1270                            );
1271                            self.project_replace(Self::Write(iter, new_fut, path.clone(), vfs));
1272                            cx.waker().wake_by_ref();
1273                            Poll::Pending
1274                        } else {
1275                            Poll::Ready(Ok(()))
1276                        }
1277                    }
1278                    Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
1279                    Poll::Pending => {
1280                        self.project_replace(Self::Write(iter, fut, path.clone(), vfs));
1281                        Poll::Pending
1282                    }
1283                }
1284            }
1285            DirChildrenWriteAsyncRefFutureProjOwn::Poison => {
1286                panic!("DirChildrenWriteAsyncRefFuture is poisoned, this should never happen");
1287            }
1288        }
1289    }
1290}
1291
1292#[cfg(feature = "resolve-path")]
1293#[cfg_attr(docsrs, doc(cfg(feature = "resolve-path")))]
1294impl<T, F, P: PathType + ?Sized> DynamicHasField for DirChildren<T, F, P>
1295where
1296    F: Filter<P>,
1297{
1298    type Inner = T;
1299
1300    fn resolve_path<Pt: OwnedPathType>(mut p: Pt, name: &str) -> Pt {
1301        p.push_segment_str(name);
1302        p
1303    }
1304}
1305
1306/// A single child of a [`DirChildren`] structure.
1307#[derive(PartialEq, Eq)]
1308#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
1309pub struct DirChild<T, P: PathType + ?Sized = Path> {
1310    /// The file name of the child.
1311    file_name: P::PathSegmentOwned,
1312    /// The parsed value of the child.
1313    value: T,
1314}
1315
1316impl<T, P: PathType + ?Sized> Clone for DirChild<T, P>
1317where
1318    T: Clone,
1319    P::PathSegmentOwned: Clone,
1320{
1321    fn clone(&self) -> Self {
1322        Self {
1323            file_name: self.file_name.clone(),
1324            value: self.value.clone(),
1325        }
1326    }
1327}
1328
1329impl<T, P: PathType + ?Sized> fmt::Debug for DirChild<T, P>
1330where
1331    T: fmt::Debug,
1332    P::PathSegmentOwned: fmt::Debug,
1333{
1334    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1335        f.debug_struct("DirChild")
1336            .field("file_name", &self.file_name)
1337            .field("value", &self.value)
1338            .finish()
1339    }
1340}
1341
1342impl<T, P: PathType + ?Sized> DirChild<T, P> {
1343    /// Creates a new [`DirChild`] with the specified file name and value.
1344    ///
1345    /// # Examples
1346    ///
1347    /// ```rust
1348    /// use std::ffi::OsString;
1349    /// use std::path::Path;
1350    /// use dir_structure::dir_children::DirChild;
1351    ///
1352    /// let d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1353    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
1354    /// assert_eq!(d.value(), &"file".to_owned());
1355    /// ```
1356    pub fn new(file_name: impl Into<P::PathSegmentOwned>, value: T) -> Self {
1357        Self {
1358            file_name: file_name.into(),
1359            value,
1360        }
1361    }
1362
1363    /// Gets the file name of the child (or the name of the directory; the last segment in the path).
1364    ///
1365    /// # Examples
1366    ///
1367    /// ```rust
1368    /// use std::ffi::OsString;
1369    /// use std::path::Path;
1370    /// use dir_structure::dir_children::DirChild;
1371    ///
1372    /// let d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1373    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
1374    /// ```
1375    pub fn file_name(&self) -> &P::PathSegmentOwned {
1376        &self.file_name
1377    }
1378
1379    /// Gets the file name of the child (or the name of the directory; the last segment in the path).
1380    ///
1381    /// Mutable reference version of [`Self::file_name`].
1382    ///
1383    /// # Examples
1384    ///
1385    /// ```rust
1386    /// use std::ffi::OsString;
1387    /// use std::path::Path;
1388    /// use dir_structure::dir_children::DirChild;
1389    ///
1390    /// let mut d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1391    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
1392    /// *d.file_name_mut() = OsString::from("new_file.txt");
1393    /// assert_eq!(d.file_name(), &OsString::from("new_file.txt"));
1394    /// ```
1395    pub fn file_name_mut(&mut self) -> &mut P::PathSegmentOwned {
1396        &mut self.file_name
1397    }
1398
1399    /// Gets the value of the child.
1400    ///
1401    /// This is the parsed value of the file / directory.
1402    ///
1403    /// # Examples
1404    ///
1405    /// ```rust
1406    /// use std::ffi::OsString;
1407    /// use std::path::Path;
1408    /// use dir_structure::dir_children::DirChild;
1409    ///
1410    /// let d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1411    /// assert_eq!(d.value(), &"file".to_owned());
1412    /// ```
1413    pub fn value(&self) -> &T {
1414        &self.value
1415    }
1416
1417    /// Gets the value of the child.
1418    ///
1419    /// This is the parsed value of the file / directory.
1420    ///
1421    /// Mutable reference version of [`Self::value`].
1422    ///
1423    /// # Examples
1424    ///
1425    /// ```rust
1426    /// use std::ffi::OsString;
1427    /// use std::path::Path;
1428    /// use dir_structure::dir_children::DirChild;
1429    ///
1430    /// let mut d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1431    /// assert_eq!(d.value(), &"file".to_owned());
1432    /// *d.value_mut() = "new_file".to_owned();
1433    /// assert_eq!(d.value(), &"new_file".to_owned());
1434    /// ```
1435    pub fn value_mut(&mut self) -> &mut T {
1436        &mut self.value
1437    }
1438
1439    /// Maps the file name of this [`DirChild`] to a new value.
1440    ///
1441    /// # Examples
1442    ///
1443    /// ```rust
1444    /// use std::ffi::OsString;
1445    /// use std::path::Path;
1446    /// use dir_structure::dir_children::DirChild;
1447    ///
1448    /// let d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1449    /// assert_eq!(d.map_file_name(|s| s.to_str().unwrap().to_uppercase()), DirChild::new("FILE.TXT", "file".to_owned()));
1450    /// ```
1451    pub fn map_file_name<F, O>(self, f: F) -> Self
1452    where
1453        F: FnOnce(P::PathSegmentOwned) -> O,
1454        O: Into<P::PathSegmentOwned>,
1455    {
1456        let file_name = f(self.file_name).into();
1457        DirChild {
1458            file_name,
1459            value: self.value,
1460        }
1461    }
1462
1463    /// Maps the value of this [`DirChild`] to a new type.
1464    ///
1465    /// This is useful for converting the value to a different type,
1466    /// for example, if you want to convert the value to a different
1467    /// type of [`DirStructureItem`].
1468    ///
1469    /// # Examples
1470    ///
1471    /// ```rust
1472    /// use std::ffi::OsString;
1473    /// use std::path::Path;
1474    /// use dir_structure::dir_children::DirChild;
1475    /// use dir_structure::std_types::FileString;
1476    ///
1477    /// let d = DirChild::<_, Path>::new("file.txt".to_owned(), "file".to_owned());
1478    /// assert_eq!(d.map_value(|v| FileString(v)), DirChild::new("file.txt".to_owned(), FileString("file".to_owned())));
1479    /// ```
1480    pub fn map_value<U, F>(self, f: F) -> DirChild<U, P>
1481    where
1482        F: FnOnce(T) -> U,
1483    {
1484        let value = f(self.value);
1485        DirChild {
1486            file_name: self.file_name,
1487            value,
1488        }
1489    }
1490}
1491
1492impl<T, P: PathType + ?Sized> Deref for DirChild<T, P> {
1493    type Target = T;
1494
1495    fn deref(&self) -> &Self::Target {
1496        &self.value
1497    }
1498}
1499
1500impl<T, P: PathType + ?Sized> DerefMut for DirChild<T, P> {
1501    fn deref_mut(&mut self) -> &mut Self::Target {
1502        &mut self.value
1503    }
1504}
1505
1506/// A [`DirChildren`] iterator. It iterates over the children of a
1507/// [`DirChildren`] structure.
1508///
1509/// See [`DirChildren::iter`] for more information.
1510pub struct DirChildrenIter<'a, T, P: PathType + ?Sized>(slice::Iter<'a, DirChild<T, P>>);
1511
1512impl<'a, T, P: PathType + ?Sized> Iterator for DirChildrenIter<'a, T, P> {
1513    type Item = &'a DirChild<T, P>;
1514
1515    fn next(&mut self) -> Option<Self::Item> {
1516        self.0.next()
1517    }
1518
1519    fn size_hint(&self) -> (usize, Option<usize>) {
1520        self.0.size_hint()
1521    }
1522}
1523
1524impl<T, P: PathType + ?Sized> ExactSizeIterator for DirChildrenIter<'_, T, P>
1525where
1526    T: DirStructureItem,
1527{
1528    fn len(&self) -> usize {
1529        self.0.len()
1530    }
1531}
1532
1533impl<T, P: PathType + ?Sized> DoubleEndedIterator for DirChildrenIter<'_, T, P>
1534where
1535    T: DirStructureItem,
1536{
1537    fn next_back(&mut self) -> Option<Self::Item> {
1538        self.0.next_back()
1539    }
1540}
1541
1542/// A mutable iterator over the children of a [`DirChildren`] structure.
1543/// This allows you to mutate the children of the
1544/// [`DirChildren`] structure while iterating over them.
1545///
1546/// See [`DirChildren::iter_mut`] for more information.
1547pub struct DirChildrenIterMut<'a, T, P: PathType + ?Sized>(slice::IterMut<'a, DirChild<T, P>>);
1548
1549impl<'a, T, P: PathType + ?Sized> Iterator for DirChildrenIterMut<'a, T, P>
1550where
1551    T: DirStructureItem,
1552{
1553    type Item = &'a mut DirChild<T, P>;
1554
1555    fn next(&mut self) -> Option<Self::Item> {
1556        self.0.next()
1557    }
1558
1559    fn size_hint(&self) -> (usize, Option<usize>) {
1560        self.0.size_hint()
1561    }
1562}
1563
1564impl<T, P: PathType + ?Sized> ExactSizeIterator for DirChildrenIterMut<'_, T, P>
1565where
1566    T: DirStructureItem,
1567{
1568    fn len(&self) -> usize {
1569        self.0.len()
1570    }
1571}
1572
1573impl<T, P: PathType + ?Sized> DoubleEndedIterator for DirChildrenIterMut<'_, T, P>
1574where
1575    T: DirStructureItem,
1576{
1577    fn next_back(&mut self) -> Option<Self::Item> {
1578        self.0.next_back()
1579    }
1580}
1581
1582impl<T, F, P: ?Sized + PathType> IntoIterator for DirChildren<T, F, P>
1583where
1584    F: Filter<P>,
1585{
1586    type Item = DirChild<T, P>;
1587    type IntoIter = DirChildrenIntoIter<T, P>;
1588
1589    fn into_iter(self) -> Self::IntoIter {
1590        DirChildrenIntoIter(self.children.into_iter())
1591    }
1592}
1593
1594impl<'a, T, F, P: PathType + ?Sized> IntoIterator for &'a DirChildren<T, F, P>
1595where
1596    F: Filter<P>,
1597{
1598    type Item = &'a DirChild<T, P>;
1599    type IntoIter = DirChildrenIter<'a, T, P>;
1600
1601    fn into_iter(self) -> Self::IntoIter {
1602        self.iter()
1603    }
1604}
1605
1606impl<'a, T, F, P: PathType + ?Sized> IntoIterator for &'a mut DirChildren<T, F, P>
1607where
1608    F: Filter<P>,
1609{
1610    type Item = &'a mut DirChild<T, P>;
1611    type IntoIter = DirChildrenIterMut<'a, T, P>;
1612
1613    fn into_iter(self) -> Self::IntoIter {
1614        self.iter_mut()
1615    }
1616}
1617
1618/// An owned iterator over the children of a [`DirChildren`] structure.
1619///
1620/// See [`DirChildren::into_iter`] for more information.
1621pub struct DirChildrenIntoIter<T, P: PathType + ?Sized>(vec::IntoIter<DirChild<T, P>>);
1622
1623impl<T, P: PathType + ?Sized> Iterator for DirChildrenIntoIter<T, P> {
1624    type Item = DirChild<T, P>;
1625
1626    fn next(&mut self) -> Option<Self::Item> {
1627        self.0.next()
1628    }
1629
1630    fn size_hint(&self) -> (usize, Option<usize>) {
1631        self.0.size_hint()
1632    }
1633}
1634
1635impl<T, P: PathType + ?Sized> ExactSizeIterator for DirChildrenIntoIter<T, P> {
1636    fn len(&self) -> usize {
1637        self.0.len()
1638    }
1639}
1640
1641impl<T, P: PathType + ?Sized> DoubleEndedIterator for DirChildrenIntoIter<T, P> {
1642    fn next_back(&mut self) -> Option<Self::Item> {
1643        self.0.next_back()
1644    }
1645}
1646
1647/// An iterator that extracts children from a [`DirChildren`] structure
1648/// that satisfy a given predicate.
1649///
1650/// See [`DirChildren::extract_if`] for more information.
1651pub struct DirChildrenExtractIf<'a, T, P: PathType + ?Sized, F: FnMut(&mut DirChild<T, P>) -> bool>(
1652    vec::ExtractIf<'a, DirChild<T, P>, F>,
1653);
1654
1655impl<'a, T, P: PathType + ?Sized, F: FnMut(&mut DirChild<T, P>) -> bool> Iterator
1656    for DirChildrenExtractIf<'a, T, P, F>
1657{
1658    type Item = DirChild<T, P>;
1659
1660    fn next(&mut self) -> Option<Self::Item> {
1661        self.0.next()
1662    }
1663
1664    fn size_hint(&self) -> (usize, Option<usize>) {
1665        self.0.size_hint()
1666    }
1667}
1668
1669/// A wrapper around [`DirChildren`] that adds the <'vfs, Vfs> generics.
1670#[macro_export]
1671macro_rules! dir_children_wrapper_with_vfs {
1672    ($vis:vis $name:ident $ty:ident $(<Path=$p_ty:ty>)?) => {
1673        $vis struct $name<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)? + 'vfs>(pub $crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path>)
1674        where
1675            Vfs: $crate::traits::vfs::VfsCore + 'vfs;
1676
1677        impl<'vfs, Vfs: $crate::traits::vfs::Vfs<'vfs $(, Path = $p_ty)?> + 'vfs> $crate::traits::sync::ReadFrom<'vfs, Vfs> for $name<'vfs, Vfs> {
1678            fn read_from(path: &Vfs::Path, vfs: ::std::pin::Pin<&'vfs Vfs>) -> $crate::error::VfsResult<Self, Vfs>
1679            where
1680                Self: Sized,
1681            {
1682                Ok(Self(<$crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path>>::read_from(path, vfs)?))
1683            }
1684        }
1685
1686        impl<'vfs, Vfs: $crate::traits::vfs::WriteSupportingVfs<'vfs $(, Path = $p_ty)?> + 'vfs> $crate::traits::sync::WriteTo<'vfs, Vfs> for $name<'vfs, Vfs> {
1687            fn write_to(&self, path: &Vfs::Path, vfs: ::std::pin::Pin<&'vfs Vfs>) -> $crate::error::VfsResult<(), Vfs> {
1688                self.0.write_to(path, vfs)
1689            }
1690        }
1691
1692        impl<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)? + 'vfs> std::ops::Deref for $name<'vfs, Vfs> {
1693            type Target = $crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path>;
1694
1695            fn deref(&self) -> &Self::Target {
1696                &self.0
1697            }
1698        }
1699
1700        impl<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)? + 'vfs> std::ops::DerefMut for $name<'vfs, Vfs> {
1701            fn deref_mut(&mut self) -> &mut Self::Target {
1702                &mut self.0
1703            }
1704        }
1705
1706        impl<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)?+ 'vfs> std::iter::IntoIterator for $name<'vfs, Vfs> {
1707            type Item = $crate::dir_children::DirChild<$ty<'vfs, Vfs>, Vfs::Path>;
1708            type IntoIter = $crate::dir_children::DirChildrenIntoIter<$ty<'vfs, Vfs>, Vfs::Path>;
1709
1710            fn into_iter(self) -> Self::IntoIter {
1711                self.0.into_iter()
1712            }
1713        }
1714
1715        impl<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)? + 'vfs> $crate::traits::resolve::DynamicHasField for $name<'vfs, Vfs> where $crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path>: $crate::traits::resolve::DynamicHasField {
1716            type Inner = <$crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path> as $crate::traits::resolve::DynamicHasField>::Inner;
1717
1718            fn resolve_path<P: $crate::traits::vfs::OwnedPathType>(p: P, field: &str) -> P {
1719                <$crate::dir_children::DirChildren<$ty<'vfs, Vfs>, $crate::NoFilter, Vfs::Path> as $crate::traits::resolve::DynamicHasField>::resolve_path(p, field)
1720            }
1721        }
1722
1723        impl<'vfs, Vfs: $crate::traits::vfs::VfsCore $(<Path = $p_ty>)? + 'vfs> $crate::traits::resolve::DynamicHasFieldNoNewtype for $name<'vfs, Vfs> {}
1724    };
1725}
1726
1727/// A structure that represents a directory where only one of the children pass the filter `F`.
1728///
1729/// This is useful if you want to select one specific file, by the [file prefix](Path::file_prefix) /
1730/// [stem](Path::file_stem), but you don't care about the extension.
1731#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1732#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
1733pub struct DirChildSingle<T, F: Filter<P>, P: PathType + ?Sized = Path> {
1734    /// The file name of the child.
1735    file_name: P::PathSegmentOwned,
1736    /// The parsed value of the child.
1737    value: T,
1738    #[cfg_attr(feature = "assert_eq", assert_eq(ignore))]
1739    _phantom: PhantomData<(F, P)>,
1740}
1741
1742impl<'a, T, F, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for DirChildSingle<T, F, Vfs::Path>
1743where
1744    T: ReadFrom<'a, Vfs>,
1745    F: Filter<Vfs::Path> + 'a,
1746{
1747    fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
1748    where
1749        Self: Sized,
1750    {
1751        let children = DirChildren::<T, F, Vfs::Path>::read_from(path, vfs)?;
1752        if children.len() != 1 {
1753            return Err(Error::UnexpectedNumberOfChildren {
1754                expected: "1",
1755                found: children.len(),
1756                path: path.owned(),
1757            });
1758        }
1759
1760        let child = children.children.into_iter().next().unwrap();
1761        Ok(DirChildSingle {
1762            file_name: child.file_name,
1763            value: child.value,
1764            _phantom: PhantomData,
1765        })
1766    }
1767}
1768
1769impl<'a, T, F: Filter<Vfs::Path>, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs>
1770    for DirChildSingle<T, F, Vfs::Path>
1771where
1772    T: WriteTo<'a, Vfs>,
1773{
1774    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
1775        let child_path = path.join_segment(&self.file_name);
1776        self.value.write_to(child_path.as_ref(), vfs)
1777    }
1778}
1779
1780impl<T, F: Filter<P>, P: PathType + ?Sized> DirChildSingle<T, F, P> {
1781    /// Creates a new [`DirChildSingle`] with the specified file name and value.
1782    ///
1783    /// # Examples
1784    ///
1785    /// ```rust
1786    /// use std::ffi::OsString;
1787    /// use dir_structure::NoFilter;
1788    /// use dir_structure::dir_children::DirChildSingle;
1789    ///
1790    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1791    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
1792    /// assert_eq!(d.value(), &"file".to_owned());
1793    /// ```
1794    pub fn new(file_name: impl Into<P::PathSegmentOwned>, value: T) -> Self {
1795        Self {
1796            file_name: file_name.into(),
1797            value,
1798            _phantom: PhantomData,
1799        }
1800    }
1801
1802    /// Gets the file name of the child (or the name of the directory; the last segment in the path).
1803    ///
1804    /// # Examples
1805    ///
1806    /// ```
1807    /// use std::ffi::OsString;
1808    /// use dir_structure::NoFilter;
1809    /// use dir_structure::dir_children::DirChildSingle;
1810    ///
1811    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1812    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
1813    /// assert_eq!(d.value(), &"file".to_owned());
1814    /// ```
1815    pub fn file_name(&self) -> &P::PathSegmentOwned {
1816        &self.file_name
1817    }
1818
1819    /// Gets the file name of the child (or the name of the directory; the last segment in the path). Mutable version of [`file_name`][Self::file_name].
1820    ///
1821    /// # Examples
1822    ///
1823    /// ```
1824    /// use std::ffi::OsString;
1825    /// use dir_structure::NoFilter;
1826    /// use dir_structure::dir_children::DirChildSingle;
1827    ///
1828    /// let mut d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1829    /// assert_eq!(d.file_name_mut(), &mut OsString::from("file.txt"));
1830    /// assert_eq!(d.value_mut(), &mut "file".to_owned());
1831    /// ```
1832    pub fn file_name_mut(&mut self) -> &mut P::PathSegmentOwned {
1833        &mut self.file_name
1834    }
1835
1836    /// Gets the value of the child.
1837    ///
1838    /// # Examples
1839    ///
1840    /// ```
1841    /// use std::ffi::OsString;
1842    /// use dir_structure::NoFilter;
1843    /// use dir_structure::dir_children::DirChildSingle;
1844    ///
1845    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1846    /// assert_eq!(d.value(), &"file".to_owned());
1847    /// ```
1848    pub fn value(&self) -> &T {
1849        &self.value
1850    }
1851
1852    /// Gets the value of the child. Mutable reference version of [`Self::value`].
1853    ///
1854    /// # Examples
1855    ///
1856    /// ```
1857    /// use std::ffi::OsString;
1858    /// use dir_structure::NoFilter;
1859    /// use dir_structure::dir_children::DirChildSingle;
1860    ///
1861    /// let mut d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1862    /// assert_eq!(d.value_mut(), &mut "file".to_owned());
1863    /// ```
1864    pub fn value_mut(&mut self) -> &mut T {
1865        &mut self.value
1866    }
1867
1868    /// Converts &[`DirChildSingle`]<T, F> to [`DirChildSingle`]<&T, F>.
1869    ///
1870    /// # Examples
1871    ///
1872    /// ```
1873    /// use std::ffi::OsString;
1874    /// use dir_structure::NoFilter;
1875    /// use dir_structure::dir_children::DirChildSingle;
1876    ///
1877    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1878    /// let d_ref: DirChildSingle<&String, NoFilter> = d.as_ref();
1879    /// assert_eq!(d_ref.file_name(), &OsString::from("file.txt"));
1880    /// assert_eq!(d_ref.value(), &&"file".to_owned());
1881    /// ```
1882    pub fn as_ref(&self) -> DirChildSingle<&T, F, P> {
1883        DirChildSingle {
1884            file_name: self.file_name.clone(),
1885            value: &self.value,
1886            _phantom: PhantomData,
1887        }
1888    }
1889
1890    /// Converts &mut [`DirChildSingle`]<T, F> to [`DirChildSingle`]<&mut T, F>.
1891    ///
1892    /// This clones the [`OsString`](std::ffi::OsString) and [`PathBuf`](std::path::PathBuf) used for the name and path.
1893    ///
1894    /// # Examples
1895    ///
1896    /// ```
1897    /// use std::ffi::OsString;
1898    /// use dir_structure::NoFilter;
1899    /// use dir_structure::dir_children::DirChildSingle;
1900    ///
1901    /// let mut d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1902    /// let mut d_mut: DirChildSingle<&mut String, NoFilter> = d.as_mut();
1903    /// d_mut.value_mut().push_str("_modified");
1904    /// assert_eq!(d.value(), &"file_modified".to_owned());
1905    /// ```
1906    pub fn as_mut(&mut self) -> DirChildSingle<&mut T, F, P> {
1907        DirChildSingle {
1908            file_name: self.file_name.clone(),
1909            value: &mut self.value,
1910            _phantom: PhantomData,
1911        }
1912    }
1913
1914    /// Maps the value of the child to a new value.
1915    ///
1916    /// # Examples
1917    ///
1918    /// ```
1919    /// use std::ffi::OsString;
1920    /// use dir_structure::NoFilter;
1921    /// use dir_structure::dir_children::DirChildSingle;
1922    ///
1923    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1924    /// let d2 = d.map(|s| s.to_uppercase());
1925    /// assert_eq!(d2.value(), &"FILE".to_owned());
1926    /// ```
1927    pub fn map<T2, F2>(self, f: F2) -> DirChildSingle<T2, F, P>
1928    where
1929        F2: FnOnce(T) -> T2,
1930    {
1931        DirChildSingle {
1932            file_name: self.file_name,
1933            value: f(self.value),
1934            _phantom: PhantomData,
1935        }
1936    }
1937
1938    /// Map the filter to another [`Filter`] type.
1939    ///
1940    /// # Examples
1941    ///
1942    /// ```
1943    /// use std::ffi::OsString;
1944    /// use dir_structure::NoFilter;
1945    /// use dir_structure::dir_children::DirChildSingle;
1946    /// use dir_structure::traits::vfs::PathType;
1947    ///
1948    /// struct Filt;
1949    ///
1950    /// impl<P: PathType + ?Sized> dir_structure::dir_children::Filter<P> for Filt {
1951    ///     fn allows(_path: &P) -> bool {
1952    ///         true
1953    ///     }
1954    /// }
1955    ///
1956    /// let d = DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned());
1957    /// let d2: DirChildSingle<_, Filt> = d.map_filter::<Filt>();
1958    /// assert_eq!(d2.file_name(), &OsString::from("file.txt"));
1959    /// assert_eq!(d2.value(), &"file".to_owned());
1960    /// ```
1961    pub fn map_filter<F2>(self) -> DirChildSingle<T, F2, P>
1962    where
1963        F2: Filter<P>,
1964    {
1965        DirChildSingle {
1966            file_name: self.file_name,
1967            value: self.value,
1968            _phantom: PhantomData,
1969        }
1970    }
1971}
1972
1973impl<T, F, P: PathType + ?Sized> fmt::Debug for DirChildSingle<T, F, P>
1974where
1975    F: Filter<P>,
1976    T: fmt::Debug,
1977    <P as PathType>::PathSegmentOwned: fmt::Debug,
1978{
1979    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1980        f.debug_struct("DirChildSingle")
1981            .field("file_name", &self.file_name)
1982            .field("value", &self.value)
1983            .finish()
1984    }
1985}
1986
1987impl<T, F, P: PathType + ?Sized> Deref for DirChildSingle<T, F, P>
1988where
1989    F: Filter<P>,
1990{
1991    type Target = T;
1992
1993    fn deref(&self) -> &Self::Target {
1994        &self.value
1995    }
1996}
1997
1998impl<T, F, P: PathType + ?Sized> DerefMut for DirChildSingle<T, F, P>
1999where
2000    F: Filter<P>,
2001{
2002    fn deref_mut(&mut self) -> &mut Self::Target {
2003        &mut self.value
2004    }
2005}
2006
2007/// A similar idea to [`DirChildSingle`], but allows for the absence of a matching entry.
2008#[derive(Clone, PartialEq, Eq)]
2009// #[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
2010pub enum DirChildSingleOpt<T, F: Filter<P>, P: PathType + ?Sized = Path> {
2011    /// The entry is absent.
2012    None,
2013    /// The entry is present.
2014    Some(DirChildSingle<T, F, P>),
2015}
2016
2017impl<T, F: Filter<P>, P: PathType + ?Sized> hash::Hash for DirChildSingleOpt<T, F, P>
2018where
2019    T: hash::Hash,
2020    <P as PathType>::PathSegmentOwned: hash::Hash,
2021{
2022    fn hash<H: hash::Hasher>(&self, state: &mut H) {
2023        match self {
2024            DirChildSingleOpt::None => {
2025                0u8.hash(state);
2026            }
2027            DirChildSingleOpt::Some(child) => {
2028                1u8.hash(state);
2029                child.hash(state);
2030            }
2031        }
2032    }
2033}
2034
2035#[cfg(feature = "assert_eq")]
2036impl<T, F: Filter<P>, P: PathType + ?Sized> assert_eq::AssertEq for DirChildSingleOpt<T, F, P>
2037where
2038    T: assert_eq::AssertEq + fmt::Debug,
2039    <P as PathType>::PathSegmentOwned: assert_eq::AssertEq + fmt::Debug,
2040{
2041    fn assert_eq(
2042        &self,
2043        other: &Self,
2044        path: &mut ::assert_eq::AssertPath,
2045        init_left: &impl fmt::Display,
2046        init_right: &impl fmt::Display,
2047    ) {
2048        match (self, other) {
2049            (DirChildSingleOpt::None, DirChildSingleOpt::None) => {}
2050            (DirChildSingleOpt::Some(a), DirChildSingleOpt::Some(b)) => {
2051                let __g = &mut *path.__guard("[Some]");
2052                a.assert_eq(b, &mut *__g.__guard(".0"), init_left, init_right);
2053            }
2054            (a, b) => panic!("DirChildSingleOpt not equal: {:?} != {:?}", a, b),
2055        }
2056    }
2057}
2058
2059impl<T, F: Filter<P>, P: PathType + ?Sized> DirChildSingleOpt<T, F, P> {
2060    /// Creates a new [`DirChildSingleOpt`] with the specified file name and value.
2061    ///
2062    /// # Examples
2063    ///
2064    /// ```rust
2065    /// use std::ffi::OsString;
2066    /// use dir_structure::dir_children::DirChildSingleOpt;
2067    /// use dir_structure::NoFilter;
2068    ///
2069    /// let DirChildSingleOpt::Some(d) = DirChildSingleOpt::<_, NoFilter>::new("file.txt", "file".to_owned()) else {
2070    ///    panic!("Expected Some variant");
2071    /// };
2072    /// assert_eq!(d.file_name(), &OsString::from("file.txt"));
2073    /// assert_eq!(d.value(), &"file".to_owned());
2074    /// ```
2075    pub fn new(file_name: impl Into<P::PathSegmentOwned>, value: T) -> Self {
2076        DirChildSingleOpt::Some(DirChildSingle::new(file_name, value))
2077    }
2078
2079    /// Returns `true` if this is a [`DirChildSingleOpt::Some`].
2080    ///
2081    /// # Examples
2082    ///
2083    /// ```
2084    /// use dir_structure::dir_children::DirChildSingleOpt;
2085    /// use dir_structure::dir_children::DirChildSingle;
2086    /// use dir_structure::NoFilter;
2087    ///
2088    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2089    /// assert!(opt.is_some());
2090    ///
2091    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2092    /// assert!(!opt.is_some());
2093    /// ```
2094    pub fn is_some(&self) -> bool {
2095        matches!(self, DirChildSingleOpt::Some(_))
2096    }
2097
2098    /// Returns `true` if this is a [`DirChildSingleOpt::None`].
2099    ///
2100    /// # Examples
2101    ///
2102    /// ```
2103    /// use dir_structure::dir_children::DirChildSingleOpt;
2104    /// use dir_structure::dir_children::DirChildSingle;
2105    /// use dir_structure::NoFilter;
2106    ///
2107    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2108    /// assert!(!opt.is_none());
2109    ///
2110    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2111    /// assert!(opt.is_none());
2112    /// ```
2113    pub fn is_none(&self) -> bool {
2114        matches!(self, DirChildSingleOpt::None)
2115    }
2116
2117    /// Converts a &[`DirChildSingleOpt`]<T, F> into a [`DirChildSingleOpt`]<&T, F>.
2118    ///
2119    /// # Examples
2120    ///
2121    /// ```
2122    /// use dir_structure::dir_children::DirChildSingleOpt;
2123    /// use dir_structure::dir_children::DirChildSingle;
2124    /// use dir_structure::NoFilter;
2125    ///
2126    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2127    /// let opt_ref = opt.as_ref();
2128    /// assert_eq!(opt_ref, DirChildSingleOpt::Some(DirChildSingle::new("file.txt", &"file".to_owned())));
2129    ///
2130    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2131    /// let opt_ref = opt.as_ref();
2132    /// assert_eq!(opt_ref, DirChildSingleOpt::None);
2133    /// ```
2134    pub fn as_ref(&self) -> DirChildSingleOpt<&T, F, P> {
2135        match self {
2136            Self::Some(child) => DirChildSingleOpt::Some(child.as_ref()),
2137            Self::None => DirChildSingleOpt::None,
2138        }
2139    }
2140
2141    /// Converts a &mut [`DirChildSingleOpt`]<T, F> into a [`DirChildSingleOpt`]<&mut T, F>.
2142    ///
2143    /// This clones the internal [`OsString`](std::ffi::OsString) and [`PathBuf`](std::path::PathBuf) used for the name and path.
2144    ///
2145    /// # Examples
2146    ///
2147    /// ```
2148    /// use dir_structure::dir_children::DirChildSingleOpt;
2149    /// use dir_structure::dir_children::DirChildSingle;
2150    ///
2151    /// use dir_structure::NoFilter;
2152    ///
2153    /// let mut opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2154    /// let mut opt_mut = opt.as_mut();
2155    /// if let DirChildSingleOpt::Some(child) = &mut opt_mut {
2156    ///     child.value_mut().push_str("_modified");
2157    /// }
2158    /// assert_eq!(opt, DirChildSingleOpt::Some(DirChildSingle::new("file.txt", "file_modified".to_owned())));
2159    ///
2160    /// let mut opt = DirChildSingleOpt::<String, NoFilter>::None;
2161    /// let mut opt_mut = opt.as_mut();
2162    /// assert_eq!(opt_mut, DirChildSingleOpt::None);
2163    /// ```
2164    pub fn as_mut(&mut self) -> DirChildSingleOpt<&mut T, F, P> {
2165        match self {
2166            Self::Some(child) => DirChildSingleOpt::Some(child.as_mut()),
2167            Self::None => DirChildSingleOpt::None,
2168        }
2169    }
2170
2171    /// Maps the value inside the [`DirChildSingleOpt`] if it exists.
2172    ///
2173    /// # Examples
2174    ///
2175    /// ```
2176    /// use dir_structure::dir_children::DirChildSingleOpt;
2177    /// use dir_structure::dir_children::DirChildSingle;
2178    /// use dir_structure::NoFilter;
2179    ///
2180    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2181    /// let opt_mapped = opt.map(|child| child.map(|v| v.to_uppercase()));
2182    /// assert_eq!(opt_mapped, DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "FILE".to_owned())));
2183    ///
2184    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2185    /// let opt_mapped = opt.map(|child| child.map(|v| v.to_uppercase()));
2186    /// assert_eq!(opt_mapped, DirChildSingleOpt::None);
2187    /// ```
2188    pub fn map<U>(
2189        self,
2190        f: impl FnOnce(DirChildSingle<T, F, P>) -> DirChildSingle<U, F, P>,
2191    ) -> DirChildSingleOpt<U, F, P> {
2192        match self {
2193            Self::Some(child) => DirChildSingleOpt::Some(f(child)),
2194            Self::None => DirChildSingleOpt::None,
2195        }
2196    }
2197
2198    /// Returns a new [`DirChildSingleOpt`] by applying the function `f` to the value inside
2199    /// the [`DirChildSingleOpt`] if it exists.
2200    ///
2201    /// # Examples
2202    ///
2203    /// ```
2204    /// use dir_structure::dir_children::DirChildSingleOpt;
2205    /// use dir_structure::dir_children::DirChildSingle;
2206    /// use dir_structure::NoFilter;
2207    ///
2208    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2209    /// let opt_and_then = opt.and_then(|child| {
2210    ///     DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new(child.file_name(), child.value().to_uppercase()))
2211    /// });
2212    /// assert_eq!(opt_and_then, DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "FILE".to_owned())));
2213    ///
2214    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2215    /// let opt_and_then = opt.and_then(|child| DirChildSingleOpt::<String, NoFilter>::None);
2216    /// assert_eq!(opt_and_then, DirChildSingleOpt::None);
2217    ///
2218    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2219    /// let opt_and_then = opt.and_then(|child| {
2220    ///     DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new(child.file_name(), child.value().to_uppercase()))
2221    /// });
2222    /// assert_eq!(opt_and_then, DirChildSingleOpt::<_, NoFilter>::None);
2223    /// ```
2224    pub fn and_then<U, F2: Filter<P2>, P2: PathType + ?Sized>(
2225        self,
2226        f: impl FnOnce(DirChildSingle<T, F, P>) -> DirChildSingleOpt<U, F2, P2>,
2227    ) -> DirChildSingleOpt<U, F2, P2> {
2228        match self {
2229            Self::Some(child) => f(child),
2230            Self::None => DirChildSingleOpt::None,
2231        }
2232    }
2233
2234    /// Returns a new [`DirChildSingleOpt`] by applying the function `f` to the value inside
2235    /// the [`DirChildSingleOpt`] if it exists.
2236    ///
2237    /// # Examples
2238    ///
2239    /// ```
2240    /// use dir_structure::dir_children::DirChildSingleOpt;
2241    /// use dir_structure::dir_children::DirChildSingle;
2242    /// use dir_structure::NoFilter;
2243    ///
2244    /// let opt = DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned()));
2245    /// let opt_or_else = opt.or_else(|| {
2246    ///     DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "FILE".to_owned()))
2247    /// });
2248    /// assert_eq!(opt_or_else, DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "file".to_owned())));
2249    ///
2250    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2251    /// let opt_or_else = opt.or_else(|| {
2252    ///     DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "FILE".to_owned()))
2253    /// });
2254    /// assert_eq!(opt_or_else, DirChildSingleOpt::Some(DirChildSingle::<_, NoFilter>::new("file.txt", "FILE".to_owned())));
2255    ///
2256    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2257    /// let opt_or_else = opt.or_else(|| DirChildSingleOpt::<String, NoFilter>::None);
2258    /// assert_eq!(opt_or_else, DirChildSingleOpt::None);
2259    /// ```
2260    pub fn or_else<F2: Filter<P>>(
2261        self,
2262        f: impl FnOnce() -> DirChildSingleOpt<T, F2, P>,
2263    ) -> DirChildSingleOpt<T, F2, P> {
2264        match self {
2265            Self::Some(child) => DirChildSingleOpt::Some(child.map_filter()),
2266            Self::None => f(),
2267        }
2268    }
2269
2270    /// Converts the [`DirChildSingleOpt`] into an `Option`.
2271    ///
2272    /// # Examples
2273    ///
2274    /// ```
2275    /// use dir_structure::dir_children::DirChildSingleOpt;
2276    /// use dir_structure::dir_children::DirChildSingle;
2277    /// use dir_structure::NoFilter;
2278    ///
2279    /// let opt = DirChildSingleOpt::Some(DirChildSingle::new("file.txt", "file".to_owned()));
2280    /// let option = opt.to_option();
2281    /// assert_eq!(option, Some(DirChildSingle::<String, NoFilter>::new("file.txt", "file".to_owned())));
2282    ///
2283    /// let opt = DirChildSingleOpt::<String, NoFilter>::None;
2284    /// let option = opt.to_option();
2285    /// assert_eq!(option, None);
2286    /// ```
2287    pub fn to_option(self) -> Option<DirChildSingle<T, F, P>> {
2288        match self {
2289            DirChildSingleOpt::Some(child) => Some(child),
2290            DirChildSingleOpt::None => None,
2291        }
2292    }
2293
2294    /// Takes the value out of the [`DirChildSingleOpt`] if the predicate `pred` returns `true`.
2295    ///
2296    /// If the predicate returns `false`, or if the [`DirChildSingleOpt`] is `None`, this returns `None`.
2297    ///
2298    /// # Examples
2299    ///
2300    /// ```
2301    /// use dir_structure::dir_children::DirChildSingleOpt;
2302    /// use dir_structure::dir_children::DirChildSingle;
2303    /// use dir_structure::NoFilter;
2304    ///
2305    /// let mut opt = DirChildSingleOpt::<String, NoFilter>::Some(DirChildSingle::new("file.txt", "file".to_owned()));
2306    /// let taken = opt.take_if(|child| child.value() == "file");
2307    /// assert_eq!(taken, DirChildSingleOpt::Some(DirChildSingle::new("file.txt", "file".to_owned())));
2308    /// assert_eq!(opt, DirChildSingleOpt::None);
2309    ///
2310    /// let mut opt = DirChildSingleOpt::<String, NoFilter>::Some(DirChildSingle::new("file.txt", "file".to_owned()));
2311    /// let taken = opt.take_if(|child| child.value() == "other");
2312    /// assert_eq!(taken, DirChildSingleOpt::None);
2313    /// assert_eq!(opt, DirChildSingleOpt::Some(DirChildSingle::new("file.txt", "file".to_owned())));
2314    ///
2315    /// let mut opt = DirChildSingleOpt::<String, NoFilter>::None;
2316    /// let taken = opt.take_if(|child| child.value() == "file");
2317    /// assert_eq!(taken, DirChildSingleOpt::None);
2318    /// assert_eq!(opt, DirChildSingleOpt::None);
2319    /// ```
2320    pub fn take_if(
2321        &mut self,
2322        pred: impl FnOnce(&DirChildSingle<T, F, P>) -> bool,
2323    ) -> DirChildSingleOpt<T, F, P> {
2324        match self {
2325            DirChildSingleOpt::Some(child) if pred(child) => {
2326                mem::replace(self, DirChildSingleOpt::None)
2327            }
2328            _ => DirChildSingleOpt::None,
2329        }
2330    }
2331}
2332
2333impl<T, F, P: PathType + ?Sized> fmt::Debug for DirChildSingleOpt<T, F, P>
2334where
2335    T: fmt::Debug,
2336    F: Filter<P>,
2337    <P as PathType>::PathSegmentOwned: fmt::Debug,
2338{
2339    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2340        match self {
2341            DirChildSingleOpt::Some(child) => f
2342                .debug_tuple("DirChildSingleOpt::Some")
2343                .field(child)
2344                .finish(),
2345            DirChildSingleOpt::None => write!(f, "DirChildSingleOpt::None"),
2346        }
2347    }
2348}
2349
2350impl<'a, T, F, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for DirChildSingleOpt<T, F, Vfs::Path>
2351where
2352    T: ReadFrom<'a, Vfs>,
2353    F: Filter<Vfs::Path> + 'a,
2354{
2355    fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
2356    where
2357        Self: Sized,
2358    {
2359        let children = DirChildren::<T, F, Vfs::Path>::read_from(path, vfs)?;
2360        if children.len() == 1 {
2361            let child = children.children.into_iter().next().unwrap();
2362            Ok(DirChildSingleOpt::Some(DirChildSingle {
2363                file_name: child.file_name,
2364                value: child.value,
2365                _phantom: PhantomData,
2366            }))
2367        } else if children.is_empty() {
2368            Ok(DirChildSingleOpt::None)
2369        } else {
2370            Err(Error::UnexpectedNumberOfChildren {
2371                expected: "0 or 1",
2372                found: children.len(),
2373                path: path.owned(),
2374            })
2375        }
2376    }
2377}
2378
2379impl<'a, T, F, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs>
2380    for DirChildSingleOpt<T, F, Vfs::Path>
2381where
2382    T: WriteTo<'a, Vfs>,
2383    F: Filter<Vfs::Path>,
2384{
2385    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
2386        match self {
2387            DirChildSingleOpt::Some(child) => child.write_to(path, vfs),
2388            DirChildSingleOpt::None => Ok(()),
2389        }
2390    }
2391}
2392
2393/// A wrapper around [`DirChildren`] that forces the creation of the directory, even if there are no children to write.
2394#[derive(Clone, PartialEq, Eq)]
2395#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
2396pub struct ForceCreateDirChildren<T, F = NoFilter, P: PathType + ?Sized = Path>
2397where
2398    F: Filter<P>,
2399{
2400    children: DirChildren<T, F, P>,
2401}
2402
2403impl<T, F, P: PathType + ?Sized> fmt::Debug for ForceCreateDirChildren<T, F, P>
2404where
2405    F: Filter<P>,
2406    T: fmt::Debug,
2407    <P as PathType>::PathSegmentOwned: fmt::Debug,
2408{
2409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2410        f.debug_struct("ForceCreateDirChildren")
2411            .field("children", &self.children)
2412            .finish()
2413    }
2414}
2415
2416impl<T, F, P> ForceCreateDirChildren<T, F, P>
2417where
2418    F: Filter<P>,
2419    P: PathType + ?Sized,
2420{
2421    /// Creates a new [`ForceCreateDirChildren`] with the specified children.
2422    ///
2423    /// # Examples
2424    ///
2425    /// ```rust
2426    /// use dir_structure::dir_children::{ForceCreateDirChildren, DirChildren};
2427    /// use dir_structure::NoFilter;
2428    ///
2429    /// let force_create = ForceCreateDirChildren::new(DirChildren::<String, NoFilter>::new());
2430    ///
2431    /// assert_eq!(force_create.len(), 0);
2432    /// ```
2433    pub fn new(children: DirChildren<T, F, P>) -> Self {
2434        ForceCreateDirChildren { children }
2435    }
2436
2437    /// Creates a new [`ForceCreateDirChildren`] from an iterator of [`DirChild`]s.
2438    ///
2439    /// # Examples
2440    ///
2441    /// ```rust
2442    /// use dir_structure::dir_children::{ForceCreateDirChildren, DirChild, DirChildren};
2443    /// use dir_structure::NoFilter;
2444    ///
2445    /// let children = vec![
2446    ///     DirChild::new("file1.txt", "content1".to_owned()),
2447    ///     DirChild::new("file2.txt", "content2".to_owned()),
2448    /// ];
2449    /// let force_create = ForceCreateDirChildren::<_, NoFilter>::with_children_from_iter(children);
2450    ///
2451    /// assert_eq!(force_create.len(), 2);
2452    /// ```
2453    pub fn with_children_from_iter<I>(iter: I) -> Self
2454    where
2455        I: IntoIterator<Item = DirChild<T, P>>,
2456    {
2457        Self::new(DirChildren::from_iter(iter))
2458    }
2459}
2460
2461impl<T, F, P: PathType + ?Sized> AsRef<DirChildren<T, F, P>> for ForceCreateDirChildren<T, F, P>
2462where
2463    F: Filter<P>,
2464{
2465    fn as_ref(&self) -> &DirChildren<T, F, P> {
2466        &self.children
2467    }
2468}
2469
2470impl<T, F, P: PathType + ?Sized> AsMut<DirChildren<T, F, P>> for ForceCreateDirChildren<T, F, P>
2471where
2472    F: Filter<P>,
2473{
2474    fn as_mut(&mut self) -> &mut DirChildren<T, F, P> {
2475        &mut self.children
2476    }
2477}
2478
2479impl<T, F, P: PathType + ?Sized> From<DirChildren<T, F, P>> for ForceCreateDirChildren<T, F, P>
2480where
2481    F: Filter<P>,
2482{
2483    fn from(children: DirChildren<T, F, P>) -> Self {
2484        ForceCreateDirChildren { children }
2485    }
2486}
2487
2488impl<T, F, P: PathType + ?Sized> From<ForceCreateDirChildren<T, F, P>> for DirChildren<T, F, P>
2489where
2490    F: Filter<P>,
2491{
2492    fn from(force_create: ForceCreateDirChildren<T, F, P>) -> Self {
2493        force_create.children
2494    }
2495}
2496
2497impl<T, F, P: PathType + ?Sized> FromIterator<DirChild<T, P>> for ForceCreateDirChildren<T, F, P>
2498where
2499    F: Filter<P>,
2500{
2501    fn from_iter<I: IntoIterator<Item = DirChild<T, P>>>(iter: I) -> Self {
2502        ForceCreateDirChildren {
2503            children: DirChildren::from_iter(iter),
2504        }
2505    }
2506}
2507
2508impl<T, F, P: PathType + ?Sized> Deref for ForceCreateDirChildren<T, F, P>
2509where
2510    F: Filter<P>,
2511{
2512    type Target = DirChildren<T, F, P>;
2513
2514    fn deref(&self) -> &Self::Target {
2515        &self.children
2516    }
2517}
2518
2519impl<T, F, P: PathType + ?Sized> DerefMut for ForceCreateDirChildren<T, F, P>
2520where
2521    F: Filter<P>,
2522{
2523    fn deref_mut(&mut self) -> &mut Self::Target {
2524        &mut self.children
2525    }
2526}
2527
2528impl<'a, T, F, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for ForceCreateDirChildren<T, F, Vfs::Path>
2529where
2530    T: ReadFrom<'a, Vfs>,
2531    F: Filter<Vfs::Path> + 'a,
2532{
2533    fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
2534    where
2535        Self: Sized,
2536    {
2537        DirChildren::<T, F, Vfs::Path>::read_from(path, vfs)
2538            .map(|children| ForceCreateDirChildren { children })
2539    }
2540}
2541
2542impl<'a, T, F, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs>
2543    for ForceCreateDirChildren<T, F, Vfs::Path>
2544where
2545    T: WriteTo<'a, Vfs>,
2546    F: Filter<Vfs::Path>,
2547{
2548    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
2549        vfs.create_dir_all(path)?;
2550
2551        self.children.write_to(path, vfs)
2552    }
2553}
2554
2555#[cfg(feature = "async")]
2556#[pin_project]
2557#[doc(hidden)]
2558pub struct ForceCreateDirChildrenReadAsyncFuture<'a, T, F, Vfs: VfsAsync>
2559where
2560    T: ReadFromAsync<'a, Vfs> + 'static,
2561    F: Filter<Vfs::Path> + Send + 'static,
2562    T::Future: Future<Output = VfsResult<T, Vfs>> + Send + Unpin,
2563{
2564    #[pin]
2565    inner: DirChildrenReadAsyncFuture<'a, T, F, Vfs>,
2566}
2567
2568#[cfg(feature = "async")]
2569#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2570impl<'a, T, F, Vfs: VfsAsync> Future for ForceCreateDirChildrenReadAsyncFuture<'a, T, F, Vfs>
2571where
2572    T: ReadFromAsync<'a, Vfs> + Send + Sync + 'static,
2573    F: Filter<Vfs::Path> + Send + 'static,
2574    T::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'static,
2575{
2576    type Output = VfsResult<ForceCreateDirChildren<T, F, Vfs::Path>, Vfs>;
2577
2578    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2579        let this = self.as_mut().project();
2580
2581        match this.inner.poll(cx) {
2582            Poll::Ready(Ok(children)) => Poll::Ready(Ok(ForceCreateDirChildren { children })),
2583            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
2584            Poll::Pending => Poll::Pending,
2585        }
2586    }
2587}
2588
2589#[cfg(feature = "async")]
2590#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2591impl<'a, T, F, Vfs: VfsAsync + 'a> ReadFromAsync<'a, Vfs>
2592    for ForceCreateDirChildren<T, F, Vfs::Path>
2593where
2594    T: ReadFromAsync<'a, Vfs> + Send + Sync + 'static,
2595    F: Filter<Vfs::Path> + Send + Sync + 'static,
2596    T::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'static,
2597{
2598    type Future = ForceCreateDirChildrenReadAsyncFuture<'a, T, F, Vfs>;
2599
2600    fn read_from_async(
2601        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
2602        vfs: Pin<&'a Vfs>,
2603    ) -> Self::Future {
2604        ForceCreateDirChildrenReadAsyncFuture {
2605            inner: DirChildren::read_from_async(path, vfs),
2606        }
2607    }
2608}
2609
2610#[cfg(feature = "async")]
2611#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2612impl<'a, T, F, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs>
2613    for ForceCreateDirChildren<T, F, Vfs::Path>
2614where
2615    T: WriteToAsync<'a, Vfs> + Send + Sync + 'static,
2616    F: Filter<Vfs::Path> + Send + Sync + 'static,
2617    T::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'a,
2618{
2619    type Future = Pin<Box<dyn Future<Output = VfsResult<(), Vfs>> + Send + 'a>>;
2620
2621    fn write_to_async(
2622        self,
2623        path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
2624        vfs: Pin<&'a Vfs>,
2625    ) -> Self::Future {
2626        Box::pin(async move {
2627            vfs.create_dir_all(path.clone()).await?;
2628
2629            self.children.write_to_async(path, vfs).await
2630        })
2631    }
2632}
2633
2634#[cfg(feature = "resolve-path")]
2635#[cfg_attr(docsrs, doc(cfg(feature = "resolve-path")))]
2636impl<T, F, P: PathType + ?Sized> DynamicHasField for ForceCreateDirChildren<T, F, P>
2637where
2638    F: Filter<P>,
2639{
2640    type Inner = T;
2641
2642    fn resolve_path<Pt: OwnedPathType>(mut p: Pt, name: &str) -> Pt {
2643        p.push_segment_str(name);
2644        p
2645    }
2646}