tauri_plugin_android_fs/api/models/dir.rs
1use std::str::FromStr;
2use serde::{Deserialize, Serialize};
3use crate::*;
4
5
6/// Directory for the app’s use only.
7///
8/// # Serialization
9/// Serialized by `serde` as the following TypeScript type:
10///
11/// ```ts
12/// // NOTE: New variants may be added in the future
13/// type PrivateDir = "Data" | "Cache" | "NoBackupData";
14/// ```
15#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
16#[non_exhaustive]
17pub enum PrivateDir {
18
19 /// The application specific persistent-data directory.
20 ///
21 /// Files stored in this directory are included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).
22 ///
23 /// The system prevents other apps and user from accessing these locations.
24 /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.
25 ///
26 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
27 ///
28 /// e.g. `/data/user/0/{app-package-name}/files`
29 ///
30 /// <https://developer.android.com/reference/android/content/Context#getFilesDir()>
31 Data,
32
33 /// The application specific cache directory.
34 ///
35 /// Files stored in this directory are **not** included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).
36 ///
37 /// The system prevents other apps and user from accessing these locations.
38 /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.
39 ///
40 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
41 ///
42 /// In addition, the system will automatically delete files in this directory as disk space is needed elsewhere on the device.
43 /// But you should not rely on this. The cache should be explicitly cleared by yourself.
44 ///
45 /// e.g. `/data/user/0/{app-package-name}/cache`
46 ///
47 /// <https://developer.android.com/reference/android/content/Context#getCacheDir()>
48 Cache,
49
50 /// The application specific persistent-data directory.
51 ///
52 /// This is similar to [`PrivateDir::Data`].
53 /// But files stored in this directory are **not** included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).
54 ///
55 /// The system prevents other apps and user from accessing these locations.
56 /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.
57 ///
58 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
59 ///
60 /// e.g. `/data/user/0/{app-package-name}/no_backup`
61 ///
62 /// <https://developer.android.com/reference/android/content/Context#getNoBackupFilesDir()>
63 NoBackupData,
64}
65
66/// Directory for the app’s use.
67///
68/// # Serialization
69/// Serialized by `serde` as the following TypeScript type:
70///
71/// ```ts
72/// // NOTE: New variants may be added in the future
73/// type AppDir = "Data" | "Cache" | "PublicMedia";
74/// ```
75#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
76#[non_exhaustive]
77pub enum AppDir {
78
79 /// The directory for persistent-data files.
80 ///
81 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
82 ///
83 /// This may be accessible by other apps.
84 ///
85 /// e.g.
86 /// - `/storage/emulated/{user-id}/Android/data/{app-package-name}/files`
87 /// - `/storage/{sd-card-id}/Android/data/{app-package-name}/files`
88 ///
89 /// <https://developer.android.com/reference/android/content/Context#getExternalFilesDirs(java.lang.String)>
90 Data,
91
92 /// The directory for cache files.
93 ///
94 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
95 ///
96 /// This may be accessible by other apps.
97 ///
98 /// e.g.
99 /// - `/storage/emulated/{user-id}/Android/data/{app-package-name}/cache`
100 /// - `/storage/{sd-card-id}/Android/data/{app-package-name}/cache`
101 ///
102 /// <https://developer.android.com/reference/android/content/Context#getExternalCacheDirs()>
103 Cache,
104
105 /// The directory for shared media files to other apps or user.
106 ///
107 /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.
108 ///
109 /// For Android 11 (API level 30) or higher,
110 /// this has been marked as deprecated.
111 /// It still works, but you should consider migrating to [`PublicStorage`](crate::api::api_async::PublicStorage).
112 ///
113 /// e.g.
114 /// - `/storage/emulated/{user-id}/Android/media/{app-package-name}`
115 /// - `/storage/{sd-card-id}/Android/media/{app-package-name}`
116 ///
117 /// <https://developer.android.com/reference/android/content/Context#getExternalMediaDirs()>
118 #[deprecated(note = "For Android 11 (API level 30) or higher, this is deprecated. Use `PublicDir` of `PublicStorage` instead.")]
119 PublicMedia
120}
121
122/// Directory in which to place files that are available to other applications and users.
123///
124/// # Serialization
125/// Serialized by `serde` as the following TypeScript type:
126///
127/// ```ts
128/// // NOTE: New variants may be added in the future
129/// type PublicDir = "Pictures" | "Movies" | "DCIM" | "Music" | "Alarms" | "Audiobooks" | "Notifications" | "Podcasts" | "Ringtones" | "Recordings" | "Documents" | "Download";
130/// ```
131#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
132#[non_exhaustive]
133pub enum PublicDir {
134
135 #[serde(untagged)]
136 Image(PublicImageDir),
137
138 #[serde(untagged)]
139 Video(PublicVideoDir),
140
141 #[serde(untagged)]
142 Audio(PublicAudioDir),
143
144 #[serde(untagged)]
145 GeneralPurpose(PublicGeneralPurposeDir),
146}
147
148/// Directory in which to place images that are available to other applications and users.
149///
150/// # Serialization
151/// Serialized by `serde` as the following TypeScript type:
152///
153/// ```ts
154/// // NOTE: New variants may be added in the future
155/// type PublicImageDir = "Pictures" | "DCIM";
156/// ```
157#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
158#[non_exhaustive]
159pub enum PublicImageDir {
160
161 Pictures,
162
163 DCIM,
164}
165
166/// Directory in which to place videos that are available to other applications and users.
167///
168/// # Serialization
169/// Serialized by `serde` as the following TypeScript type:
170///
171/// ```ts
172/// // NOTE: New variants may be added in the future
173/// type PublicVideoDir = "Movies" | "DCIM" | "Pictures";
174/// ```
175#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
176#[non_exhaustive]
177pub enum PublicVideoDir {
178
179 Movies,
180
181 DCIM,
182
183 Pictures,
184}
185
186/// Directory in which to place audios that are available to other applications and users.
187///
188/// # Serialization
189/// Serialized by `serde` as the following TypeScript type:
190///
191/// ```ts
192/// // NOTE: New variants may be added in the future
193/// type PublicAudioDir = "Music" | "Alarms" | "Audiobooks" | "Notifications" | "Podcasts" | "Ringtones" | "Recordings";
194/// ```
195#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
196#[non_exhaustive]
197pub enum PublicAudioDir {
198
199 Music,
200
201 Alarms,
202
203 /// This is not available on Android 9 (API level 28) and lower.
204 Audiobooks,
205
206 Notifications,
207
208 Podcasts,
209
210 Ringtones,
211
212 /// This is not available on Android 11 (API level 30) and lower.
213 Recordings,
214}
215
216/// Directory in which to place files that are available to other applications and users.
217///
218/// # Serialization
219/// Serialized by `serde` as the following TypeScript type:
220///
221/// ```ts
222/// // NOTE: New variants may be added in the future
223/// type PublicGeneralPurposeDir = "Documents" | "Download";
224/// ```
225#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
226#[non_exhaustive]
227pub enum PublicGeneralPurposeDir {
228
229 Documents,
230
231 /// This is not the plural "Downloads", but the singular "Download".
232 /// <https://developer.android.com/reference/android/os/Environment#DIRECTORY_DOWNLOADS>
233 Download,
234}
235
236impl std::fmt::Display for PublicImageDir {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 match self {
239 PublicImageDir::Pictures => write!(f, "Pictures"),
240 PublicImageDir::DCIM => write!(f, "DCIM"),
241 }
242 }
243}
244
245impl std::fmt::Display for PublicVideoDir {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 match self {
248 PublicVideoDir::Movies => write!(f, "Movies"),
249 PublicVideoDir::DCIM => write!(f, "DCIM"),
250 PublicVideoDir::Pictures => write!(f, "Pictures")
251 }
252 }
253}
254
255impl std::fmt::Display for PublicAudioDir {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 match self {
258 PublicAudioDir::Music => write!(f, "Music"),
259 PublicAudioDir::Alarms => write!(f, "Alarms"),
260 PublicAudioDir::Audiobooks => write!(f, "Audiobooks"),
261 PublicAudioDir::Notifications => write!(f, "Notifications"),
262 PublicAudioDir::Podcasts => write!(f, "Podcasts"),
263 PublicAudioDir::Ringtones => write!(f, "Ringtones"),
264 PublicAudioDir::Recordings => write!(f, "Recordings"),
265 }
266 }
267}
268
269impl std::fmt::Display for PublicGeneralPurposeDir {
270 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
271 match self {
272 PublicGeneralPurposeDir::Documents => write!(f, "Documents"),
273 PublicGeneralPurposeDir::Download => write!(f, "Download"),
274 }
275 }
276}
277
278impl std::fmt::Display for PublicDir {
279 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
280 match self {
281 PublicDir::Image(p) => p.fmt(f),
282 PublicDir::Video(p) => p.fmt(f),
283 PublicDir::Audio(p) => p.fmt(f),
284 PublicDir::GeneralPurpose(p) => p.fmt(f),
285 }
286 }
287}
288
289macro_rules! impl_into_pubdir {
290 ($target: ident, $wrapper: ident) => {
291 impl From<$target> for PublicDir {
292 fn from(value: $target) -> Self {
293 Self::$wrapper(value)
294 }
295 }
296 };
297}
298impl_into_pubdir!(PublicImageDir, Image);
299impl_into_pubdir!(PublicVideoDir, Video);
300impl_into_pubdir!(PublicAudioDir, Audio);
301impl_into_pubdir!(PublicGeneralPurposeDir, GeneralPurpose);
302
303impl FromStr for PublicImageDir {
304 type Err = Error;
305
306 fn from_str(s: &str) -> Result<Self> {
307 if s.eq_ignore_ascii_case("pictures") {
308 Ok(PublicImageDir::Pictures)
309 }
310 else if s.eq_ignore_ascii_case("dcim") {
311 Ok(PublicImageDir::DCIM)
312 }
313 else {
314 Err(Error::with(format!("invalid PublicImageDir: {s}")))
315 }
316 }
317}
318
319impl FromStr for PublicVideoDir {
320 type Err = Error;
321
322 fn from_str(s: &str) -> Result<Self> {
323 if s.eq_ignore_ascii_case("movies") {
324 Ok(PublicVideoDir::Movies)
325 }
326 else if s.eq_ignore_ascii_case("dcim") {
327 Ok(PublicVideoDir::DCIM)
328 }
329 else if s.eq_ignore_ascii_case("pictures") {
330 Ok(PublicVideoDir::Pictures)
331 }
332 else {
333 Err(Error::with(format!("invalid PublicVideoDir: {s}")))
334 }
335 }
336}
337
338impl FromStr for PublicAudioDir {
339 type Err = Error;
340
341 fn from_str(s: &str) -> Result<Self> {
342 if s.eq_ignore_ascii_case("music") {
343 Ok(PublicAudioDir::Music)
344 }
345 else if s.eq_ignore_ascii_case("alarms") {
346 Ok(PublicAudioDir::Alarms)
347 }
348 else if s.eq_ignore_ascii_case("audiobooks") {
349 Ok(PublicAudioDir::Audiobooks)
350 }
351 else if s.eq_ignore_ascii_case("notifications") {
352 Ok(PublicAudioDir::Notifications)
353 }
354 else if s.eq_ignore_ascii_case("podcasts") {
355 Ok(PublicAudioDir::Podcasts)
356 }
357 else if s.eq_ignore_ascii_case("ringtones") {
358 Ok(PublicAudioDir::Ringtones)
359 }
360 else if s.eq_ignore_ascii_case("recordings") {
361 Ok(PublicAudioDir::Recordings)
362 }
363 else {
364 Err(Error::with(format!("invalid PublicAudioDir: {s}")))
365 }
366 }
367}
368
369impl FromStr for PublicGeneralPurposeDir {
370 type Err = Error;
371
372 fn from_str(s: &str) -> Result<Self> {
373 if s.eq_ignore_ascii_case("documents") {
374 Ok(PublicGeneralPurposeDir::Documents)
375 }
376 else if s.eq_ignore_ascii_case("download") || s.eq_ignore_ascii_case("downloads") {
377 Ok(PublicGeneralPurposeDir::Download)
378 }
379 else {
380 Err(Error::with(format!("invalid PublicGeneralPurposeDir: {s}")))
381 }
382 }
383}
384
385impl FromStr for PublicDir {
386 type Err = Error;
387
388 fn from_str(s: &str) -> Result<Self> {
389 if let Ok(v) = PublicImageDir::from_str(s) {
390 Ok(PublicDir::Image(v))
391 }
392 else if let Ok(v) = PublicVideoDir::from_str(s) {
393 Ok(PublicDir::Video(v))
394 }
395 else if let Ok(v) = PublicAudioDir::from_str(s) {
396 Ok(PublicDir::Audio(v))
397 }
398 else if let Ok(v) = PublicGeneralPurposeDir::from_str(s) {
399 Ok(PublicDir::GeneralPurpose(v))
400 }
401 else {
402 Err(Error::with(format!("invalid PublicDir: {s}")))
403 }
404 }
405}