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