Skip to main content

tauri_plugin_android_fs/api/models/
entry.rs

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