1use std::collections::btree_set::BTreeSet;
2use std::ffi::OsString;
3use std::io;
4use std::path::Path;
5
6#[derive(Debug, Clone, Eq, PartialEq)]
8pub struct Entry {
9 pub name: OsString,
10 pub kind: EntryKind,
11}
12
13#[derive(Debug, Clone, Copy, Eq, PartialEq)]
15pub enum EntryKind {
16 File,
17 Dir,
18 }
21
22pub struct Entries<'a> {
24 inner: Box<dyn Iterator<Item = io::Result<Entry>> + 'a>,
25}
26
27impl<'a> Entries<'a> {
28 pub fn new<I>(iter: I) -> Self
29 where
30 I: IntoIterator<Item = <Entries<'a> as Iterator>::Item>,
31 <I as IntoIterator>::IntoIter: 'a,
32 {
33 Self {
34 inner: Box::new(iter.into_iter()),
35 }
36 }
37}
38
39impl Iterator for Entries<'_> {
40 type Item = io::Result<Entry>;
41
42 fn next(&mut self) -> Option<Self::Item> {
43 self.inner.next()
44 }
45}
46
47pub trait Store {
49 type File;
50
51 fn open_path(&self, path: &Path) -> io::Result<Self::File>;
52
53 fn entries_path(&self, _: &Path) -> io::Result<Entries> {
55 unimplemented!("entries_path is not implemented.")
56 }
57}
58
59pub trait StoreExt: Store {
61 fn entries<P: AsRef<Path>>(&self, path: P) -> io::Result<Entries> {
62 <Self as Store>::entries_path(self, &crate::index::normalize_path(path.as_ref()))
63 }
64
65 fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<Self::File> {
66 <Self as Store>::open_path(self, &crate::index::normalize_path(path.as_ref()))
67 }
68}
69
70impl<T: Store> StoreExt for T {}
71
72pub(crate) struct MapFile<S, F> {
73 store: S,
74 clo: F,
75}
76
77impl<S, F> MapFile<S, F> {
78 pub(crate) fn new(store: S, closure: F) -> Self {
79 Self {
80 store,
81 clo: closure,
82 }
83 }
84}
85
86impl<U, S, F> Store for MapFile<S, F>
87where
88 S: Store,
89 F: Fn(S::File) -> U,
90{
91 type File = U;
92 #[inline]
93 fn open_path(&self, path: &Path) -> io::Result<Self::File> {
94 match self.store.open_path(path) {
95 Ok(file) => Ok((self.clo)(file)),
96 Err(err) => Err(err),
97 }
98 }
99
100 #[inline]
101 fn entries_path(&self, path: &Path) -> io::Result<Entries> {
102 self.store.entries_path(path)
103 }
104}
105
106struct TupleEntries<I> {
109 inner: I,
110 set: BTreeSet<OsString>,
111}
112
113impl<I> TupleEntries<I> {
114 fn new(inner: I) -> Self {
115 Self {
116 inner,
117 set: BTreeSet::new(),
118 }
119 }
120}
121
122impl<I> Iterator for TupleEntries<I>
123where
124 I: Iterator<Item = io::Result<Entry>>,
125{
126 type Item = <I as Iterator>::Item;
127 fn next(&mut self) -> Option<Self::Item> {
128 loop {
129 match self.inner.next() {
130 None => return None,
131 Some(Err(e)) => return Some(Err(e)),
132 Some(Ok(file)) => {
133 if self.set.insert(file.name.clone()) {
134 return Some(Ok(file));
135 }
136 }
137 }
138 }
139 }
140}
141
142store_tuples! { A, B, C, D, E, F, G, H, I, J, K, }