tauri_plugin_android_fs/models/
entry.rs

1use serde::{Deserialize, Serialize};
2use crate::*;
3
4#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
5#[serde(tag = "type")]
6pub enum EntryType {
7
8    File {
9        #[serde(rename = "mimeType")]
10        mime_type: String,
11    },
12
13    Dir,
14}
15
16impl EntryType {
17
18    pub fn is_file(&self) -> bool {
19        matches!(self, Self::File { .. })
20    }
21
22    pub fn is_dir(&self) -> bool {
23        matches!(self, Self::Dir)
24    }
25
26    /// If a file, this is no None.  
27    /// If a directory, this is None.  
28    pub fn file_mime_type(&self) -> Option<&str> {
29        match self {
30            EntryType::File { mime_type } => Some(&mime_type),
31            EntryType::Dir => None,
32        }
33    }
34
35    /// If a file, this is no None.  
36    /// If a directory, this is None.  
37    pub fn into_file_mime_type(self) -> Option<String> {
38        match self {
39            EntryType::File { mime_type } => Some(mime_type),
40            EntryType::Dir => None,
41        }
42    }
43
44    /// If a file, this is no Err.  
45    /// If a directory, this is Err.  
46    pub fn file_mime_type_or_err(&self) -> Result<&str> {
47        self.file_mime_type().ok_or_else(|| Error::with("This is not a file"))
48    }
49
50    /// If a file, this is no Err.  
51    /// If a directory, this is Err.  
52    pub fn into_file_mime_type_or_err(self) -> Result<String> {
53        self.into_file_mime_type().ok_or_else(|| Error::with("This is not a file"))
54    }
55}
56
57#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
58#[serde(rename_all = "camelCase")]
59pub enum Entry {
60
61    #[non_exhaustive]
62    File {
63        uri: FileUri,
64        name: String,
65        last_modified: std::time::SystemTime,
66        len: u64,
67        mime_type: String,
68    },
69
70    #[non_exhaustive]
71    Dir {
72        uri: FileUri,
73        name: String,
74        last_modified: std::time::SystemTime,
75    }
76}
77
78impl Entry {
79
80    pub fn is_file(&self) -> bool {
81        matches!(self, Self::File { .. })
82    }
83
84    pub fn is_dir(&self) -> bool {
85        matches!(self, Self::Dir { .. })
86    }
87
88    pub fn uri(&self) -> &FileUri {
89        match self {
90            Entry::File { uri, .. } => uri,
91            Entry::Dir { uri, .. } => uri,
92        }
93    }
94
95    pub fn name(&self) -> &str {
96        match self {
97            Entry::File { name, .. } => name,
98            Entry::Dir { name, .. } => name,
99        }
100    }
101
102    pub fn last_modified(&self) -> std::time::SystemTime {
103        match self {
104            Entry::File { last_modified, .. } => *last_modified,
105            Entry::Dir { last_modified, .. } => *last_modified,
106        }
107    }
108
109    /// If file, this is no None.  
110    /// If directory, this is None.  
111    pub fn file_mime_type(&self) -> Option<&str> {
112        match self {
113            Entry::File { mime_type, .. } => Some(mime_type),
114            Entry::Dir { .. } => None,
115        }
116    }
117
118    /// If a file, this is no None.  
119    /// If a directory, this is None.  
120    pub fn file_len(&self) -> Option<u64> {
121        match self {
122            Entry::File { len, .. } => Some(*len),
123            Entry::Dir { .. } => None,
124        }
125    }
126
127    /// If a file, this is no Err.  
128    /// If a directory, this is Err.  
129    pub fn file_mime_type_or_err(&self) -> Result<&str> {
130        self.file_mime_type().ok_or_else(|| Error::with("This is not a file"))
131    }
132
133    /// If a file, this is no Err.  
134    /// If a directory, this is Err.  
135    pub fn file_len_or_err(&self) -> Result<u64> {
136        self.file_len().ok_or_else(|| Error::with("This is not a file"))
137    }
138 }
139
140#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
141#[serde(rename_all = "camelCase")]
142pub enum OptionalEntry {
143
144    #[non_exhaustive]
145    File {
146        /// If `EntryOptions { uri, .. }` is set to `true`, 
147        /// this will never be `None`.
148        uri: Option<FileUri>,
149
150        /// If `EntryOptions { name, .. }` is set to `true`, 
151        /// this will never be `None`.
152        name: Option<String>,
153
154        /// If `EntryOptions { last_modified, .. }` is set to `true`, 
155        /// this will never be `None`.
156        last_modified: Option<std::time::SystemTime>,
157
158        /// If `EntryOptions { len, .. }` is set to `true`, 
159        /// this will never be `None`.
160        len: Option<u64>,
161
162        /// If `EntryOptions { mime_type, .. }` is set to `true`, 
163        /// this will never be `None`.
164        mime_type: Option<String>,
165    },
166
167    #[non_exhaustive]
168    Dir {
169        /// If `EntryOptions { uri, .. }` is set to `true`, 
170        /// this will never be `None`.
171        uri: Option<FileUri>,
172
173        /// If `EntryOptions { name, .. }` is set to `true`, 
174        /// this will never be `None`.
175        name: Option<String>,
176
177        /// If `EntryOptions { last_modified, .. }` is set to `true`, 
178        /// this will never be `None`.
179        last_modified: Option<std::time::SystemTime>,
180    }
181}
182
183impl OptionalEntry {
184
185    pub fn is_file(&self) -> bool {
186        matches!(self, Self::File { .. })
187    }
188
189    pub fn is_dir(&self) -> bool {
190        matches!(self, Self::Dir { .. })
191    }
192
193    /// If `EntryOptions { uri, .. }` is set to `true`, 
194    /// this will never be `None`.
195    pub fn into_uri(self) -> Option<FileUri> {
196        match self {
197            Self::File { uri, .. } => uri,
198            Self::Dir { uri, .. } => uri,
199        }
200    }
201    
202    /// If `EntryOptions { uri, .. }` is set to `true`, 
203    /// this will never be error.
204    pub fn into_uri_or_err(self) -> Result<FileUri> {
205        self.into_uri().ok_or_else(|| Error::missing_value("uri"))
206    }
207
208    /// If `EntryOptions { uri, .. }` is set to `true`, 
209    /// this will never be error.
210    pub fn uri_or_err(&self) -> Result<&FileUri> {
211        self.uri().ok_or_else(|| Error::missing_value("uri"))
212    }
213
214    /// If `EntryOptions { name, .. }` is set to `true`, 
215    /// this will never be error.
216    pub fn name_or_err(&self) -> Result<&str> {
217        self.name().ok_or_else(|| Error::missing_value("name"))
218    }
219
220    /// If `EntryOptions { last_modified, .. }` is set to `true`, 
221    /// this will never be error.
222    pub fn last_modified_or_err(&self) -> Result<std::time::SystemTime> {
223        self.last_modified().ok_or_else(|| Error::missing_value("last_modified"))
224    }
225
226    /// If a file and `EntryOptions { mime_type, .. }` is set to `true`, 
227    /// this will never be error.
228    pub fn file_mime_type_or_err(&self) -> Result<&str> {
229        self.file_mime_type().ok_or_else(|| Error::with("Not file or missing value: mime_type"))
230    }
231
232    /// If a file and `EntryOptions { len, .. }` is set to `true`, 
233    /// this will never be error.
234    pub fn file_len_or_err(&self) -> Result<u64> {
235        self.file_len().ok_or_else(|| Error::with("Not file or missing value: len"))
236    }
237
238    /// If `EntryOptions { uri, .. }` is set to `true`, 
239    /// this will never be `None`.
240    pub fn uri(&self) -> Option<&FileUri> {
241        match self {
242            Self::File { uri, .. } => uri.as_ref(),
243            Self::Dir { uri, .. } => uri.as_ref(),
244        }
245    }
246
247    /// If `EntryOptions { name, .. }` is set to `true`, 
248    /// this will never be `None`.
249    pub fn name(&self) -> Option<&str> {
250        match self {
251            Self::File { name, .. } => name.as_deref(),
252            Self::Dir { name, .. } => name.as_deref(),
253        }
254    }
255
256    /// If `EntryOptions { last_modified, .. }` is set to `true`, 
257    /// this will never be `None`.
258    pub fn last_modified(&self) -> Option<std::time::SystemTime> {
259        match self {
260            Self::File { last_modified, .. } => *last_modified,
261            Self::Dir { last_modified, .. } => *last_modified,
262        }
263    }
264
265    /// If a file and `EntryOptions { mime_type, .. }` is set to `true`, 
266    /// this will never be `None`.
267    pub fn file_mime_type(&self) -> Option<&str> {
268        match self {
269            Self::File { mime_type, .. } => mime_type.as_deref(),
270            Self::Dir { .. } => None,
271        }
272    }
273
274    /// If a file and `EntryOptions { len, .. }` is set to `true`, 
275    /// this will never be `None`.
276    pub fn file_len(&self) -> Option<u64> {
277        match self {
278            Self::File { len, .. } => *len,
279            Self::Dir { .. } => None,
280        }
281    }
282 }
283
284#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
285#[serde(rename_all = "camelCase")]
286pub struct EntryOptions {
287    pub uri: bool,
288    pub name: bool,
289    pub last_modified: bool,
290    pub len: bool,
291    pub mime_type: bool,
292}
293
294impl EntryOptions {
295
296    pub const ALL: EntryOptions = EntryOptions {
297        uri: true,
298        name: true,
299        last_modified: true,
300        len: true,
301        mime_type: true
302    };
303
304    pub const NONE: EntryOptions = EntryOptions {
305        uri: false,
306        name: false,
307        last_modified: false,
308        len: false,
309        mime_type: false
310    };
311
312    pub const URI_ONLY: EntryOptions = EntryOptions {
313        uri: true,
314        ..Self::NONE
315    };
316
317    pub const URI_AND_NAME: EntryOptions = EntryOptions {
318        uri: true,
319        name: true,
320        ..Self::NONE
321    };
322}
323
324impl TryFrom<OptionalEntry> for Entry {
325    type Error = crate::Error;
326
327    fn try_from(value: OptionalEntry) -> std::result::Result<Self, Self::Error> {
328        Ok(match value {
329            OptionalEntry::File { uri, name, last_modified, len, mime_type } => Entry::File {
330                uri: uri.ok_or_else(|| Error::missing_value("uri"))?,
331                name: name.ok_or_else(|| Error::missing_value("name"))?,
332                last_modified: last_modified.ok_or_else(|| Error::missing_value("last_modified"))?,
333                len: len.ok_or_else(|| Error::missing_value("len"))?,
334                mime_type: mime_type.ok_or_else(|| Error::missing_value("mime_type"))?,
335            },
336            OptionalEntry::Dir { uri, name, last_modified } => Entry::Dir {
337                uri: uri.ok_or_else(|| Error::missing_value("uri"))?,
338                name: name.ok_or_else(|| Error::missing_value("name"))?,
339                last_modified: last_modified.ok_or_else(|| Error::missing_value("last_modified"))?,
340            },
341        })
342    }
343}