virtual_fs/
filesystems.rs

1use crate::FileSystem;
2
3/// A chain of one or more [`FileSystem`]s.
4pub trait FileSystems<'a>: 'a {
5    // FIXME(Michael-F-Bryan): Rewrite this to use GATs when we bump the MSRV to
6    // 1.65 or higher. That'll get rid of all the lifetimes and HRTBs.
7    type Iter: IntoIterator<Item = &'a (dyn FileSystem + Send)> + Send + 'a;
8
9    /// Get something that can be used to iterate over the underlying
10    /// filesystems.
11    fn filesystems(&'a self) -> Self::Iter;
12}
13
14impl<'a, 'b, S> FileSystems<'a> for &'b S
15where
16    S: FileSystems<'a> + 'b,
17    'b: 'a,
18{
19    type Iter = S::Iter;
20
21    fn filesystems(&'a self) -> Self::Iter {
22        (**self).filesystems()
23    }
24}
25
26impl<'a, T> FileSystems<'a> for Vec<T>
27where
28    T: FileSystem + Send,
29{
30    type Iter = <[T] as FileSystems<'a>>::Iter;
31
32    fn filesystems(&'a self) -> Self::Iter {
33        self[..].filesystems()
34    }
35}
36
37impl<'a, T, const N: usize> FileSystems<'a> for [T; N]
38where
39    T: FileSystem + Send,
40{
41    type Iter = [&'a (dyn FileSystem + Send); N];
42
43    fn filesystems(&'a self) -> Self::Iter {
44        // TODO: rewrite this when array::each_ref() is stable
45        let mut i = 0;
46        [(); N].map(|_| {
47            let f = &self[i] as &(dyn FileSystem + Send);
48            i += 1;
49            f
50        })
51    }
52}
53
54impl<'a, T> FileSystems<'a> for [T]
55where
56    T: FileSystem + Send,
57{
58    type Iter = std::iter::Map<std::slice::Iter<'a, T>, fn(&T) -> &(dyn FileSystem + Send)>;
59
60    fn filesystems(&'a self) -> Self::Iter {
61        self.iter().map(|fs| fs as &(dyn FileSystem + Send))
62    }
63}
64
65impl<'a> FileSystems<'a> for () {
66    type Iter = std::iter::Empty<&'a (dyn FileSystem + Send)>;
67
68    fn filesystems(&'a self) -> Self::Iter {
69        std::iter::empty()
70    }
71}
72
73macro_rules! count {
74    ($first:tt $($rest:tt)*) => {
75        1 + count!($($rest)*)
76    };
77    () => { 0 };
78}
79
80macro_rules! tuple_filesystems {
81    ($first:ident $(, $rest:ident)* $(,)?) => {
82        impl<'a, $first, $( $rest ),*> FileSystems<'a> for ($first, $($rest),*)
83        where
84            $first: FileSystem,
85            $($rest: FileSystem),*
86        {
87            type Iter = [&'a (dyn FileSystem + Send); count!($first $($rest)*)];
88
89            fn filesystems(&'a self) -> Self::Iter {
90                #[allow(non_snake_case)]
91                let ($first, $($rest),*) = self;
92
93                [
94                    $first as &(dyn FileSystem + Send),
95                    $($rest),*
96                ]
97            }
98
99        }
100
101        tuple_filesystems!($($rest),*);
102    };
103    () => {};
104}
105
106tuple_filesystems!(
107    F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16,
108);