Skip to main content

std/fs/
dirs.rs

1use crate::path::{Path, PathBuf};
2use crate::sys::fs::{ExtraHomeDirs, ExtraMediaDirs};
3
4/// Common user directory paths used for user-specific application files.
5///
6/// It is not required that the user directories are accessible by the current
7/// user, nor that there is a directory at that path. A robust application
8/// should handle the case where user directories are incorrectly configured.
9///
10/// Even when configured correctly, multiple paths may point to the same location.
11/// You should not assume that a file written relative to one directory will not
12/// conflict with the same relative path in a different home directory.
13///
14/// # Platform-specific behavior
15///
16/// As the filesystem conventions for discovering directories varies between
17/// operating systems, constructors for `HomeDirs` that use the host platform's
18/// conventions are provided as extension traits under the `std::os` module.
19#[unstable(feature = "fs_home_dirs", issue = "162082")]
20#[derive(Debug, Clone)]
21pub struct HomeDirs {
22    pub(crate) cache: Option<PathBuf>,
23    pub(crate) config: Option<PathBuf>,
24    pub(crate) data: Option<PathBuf>,
25    pub(crate) state: Option<PathBuf>,
26    #[cfg_attr(not(unix), expect(dead_code, reason = "no extra home dirs"))]
27    pub(crate) extra: ExtraHomeDirs,
28}
29
30/// Common user directory paths used for user-specific media files.
31///
32/// It is not required that the media directories are accessible by the current
33/// user, nor that there is a directory at that path. A robust application
34/// should handle the case where media directories are incorrectly configured.
35///
36/// Even when configured correctly, multiple paths may point to the same location.
37/// You should not assume that a file written relative to one directory will not
38/// conflict with the same relative path in a different media directory.
39///
40/// # Platform-specific behavior
41///
42/// As the filesystem conventions for discovering directories varies between
43/// operating systems, constructors for `MediaDirs` that use the host platform's
44/// conventions are provided as extension traits under the `std::os` module.
45#[unstable(feature = "fs_media_dirs", issue = "162083")]
46#[derive(Debug, Clone)]
47pub struct MediaDirs {
48    pub(crate) desktop: Option<PathBuf>,
49    pub(crate) documents: Option<PathBuf>,
50    pub(crate) downloads: Option<PathBuf>,
51    pub(crate) music: Option<PathBuf>,
52    pub(crate) pictures: Option<PathBuf>,
53    pub(crate) videos: Option<PathBuf>,
54    #[cfg_attr(not(unix), expect(dead_code, reason = "no extra media dirs"))]
55    pub(crate) extra: ExtraMediaDirs,
56}
57
58// NB: HomeDirs and MediaDirs intentionally do not implement Default. Self::empty()
59//     is a logical default, but users may also intuit the default to use default
60//     platform conventions. Omitting Default pushes users to explicitly choose.
61
62impl HomeDirs {
63    /// Create a known user directory set with no known directories.
64    ///
65    /// This is useful with the builder `set_*` methods to create a `HomeDirs`
66    /// with exactly the directories you want, without any other defaults.
67    #[unstable(feature = "fs_home_dirs", issue = "162082")]
68    pub fn empty() -> Self {
69        Self { cache: None, config: None, data: None, state: None, extra: Default::default() }
70    }
71
72    /// A base directory relative to which user-specific non-essential cache
73    /// data files should be stored.
74    ///
75    /// "Cache" files are temporary data that can be used to cache redundant
76    /// work of an application, but which can be discarded arbitrarily and
77    /// recreated as necessary. Files in this directory may potentially be
78    /// automatically purged any time they are not currently open, or they
79    /// may not, depending on system configuration. A robust application
80    /// should ensure that its caches do not grow without a reasonable bound.
81    ///
82    /// This is the same directory for all applications. Applications should
83    /// use a subdirectory for application-specific cache files.
84    ///
85    /// # Platform-specific behavior
86    ///
87    /// When constructed using platform-specific conventions, the value is:
88    ///
89    /// | OS | Path |
90    /// | -- | ---- |
91    /// | [XDG] (Linux) | `${XDG_CACHE_HOME:-$HOME/.cache}` |
92    /// | [Darwin] (macOS) | [`NSCachesDirectory`] (`$HOME/Library/Caches`) |
93    /// | [Windows] | [`{FOLDERID_LocalAppData}`] (`%LOCALAPPDATA%`) |
94    ///
95    /// Other paths can be configured via [`set_cache_home`](Self::set_cache_home).
96    ///
97    /// [XDG]: crate::os::unix::fs::HomeDirsExt
98    /// [Darwin]: crate::os::darwin::fs::HomeDirsExt
99    /// [Windows]: crate::os::windows::fs::HomeDirsExt
100    /// [`NSCachesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/cachesdirectory?language=objc
101    /// [`{FOLDERID_LocalAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_localappdata
102    #[unstable(feature = "fs_home_dirs", issue = "162082")]
103    pub fn cache_home(&self) -> Option<&Path> {
104        self.cache.as_deref()
105    }
106
107    /// A base directory relative to which user-specific configuration files
108    /// should be stored.
109    ///
110    /// "Config" files are configuration managed by the user, either by editing
111    /// the files directly or through a managing application. Configuration is
112    /// generally expected to be meaningful to the user and portable enough to
113    /// back up and synchronize across the same user's account on multiple
114    /// systems.
115    ///
116    /// This is the same directory for all applications. Applications should
117    /// use a subdirectory for application-specific configuration files.
118    ///
119    /// # Platform-specific behavior
120    ///
121    /// When constructed using platform-specific conventions, the value is:
122    ///
123    /// | OS | Path |
124    /// | -- | ---- |
125    /// | [XDG] (Linux) | `${XDG_CONFIG_HOME:-$HOME/.config}` |
126    /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) |
127    /// | [Windows] | [`{FOLDERID_RoamingAppData}`] (`%APPDATA%`) |
128    ///
129    /// Other paths can be configured via [`set_config_home`](Self::set_config_home).
130    ///
131    /// [XDG]: crate::os::unix::fs::HomeDirsExt
132    /// [Darwin]: crate::os::darwin::fs::HomeDirsExt
133    /// [Windows]: crate::os::windows::fs::HomeDirsExt
134    /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc
135    /// [`{FOLDERID_RoamingAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_roamingappdata
136    #[unstable(feature = "fs_home_dirs", issue = "162082")]
137    pub fn config_home(&self) -> Option<&Path> {
138        self.config.as_deref()
139    }
140
141    /// A base directory relative to which user-specific data files should be
142    /// stored.
143    ///
144    /// "Data" files are application-specific data that is meaningful to the
145    /// user in some way and does not implicitly rely on system configuration
146    /// or details of how the application is installed otherwise irrelevant to
147    /// the user. As such, data makes sense to back up and synchronize between
148    /// the same user's account on multiple systems. If a file is specific to
149    /// a single machine, it's probably [state](Self::state_home).
150    ///
151    /// This is the same directory for all applications. Applications should
152    /// use a subdirectory for application-specific data files.
153    ///
154    /// # Platform-specific behavior
155    ///
156    /// When constructed using platform-specific conventions, the value is:
157    ///
158    /// | OS | Path |
159    /// | -- | ---- |
160    /// | [XDG] (Linux) | `${XDG_DATA_HOME:-$HOME/.local/share}` |
161    /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) |
162    /// | [Windows] | [`{FOLDERID_RoamingAppData}`] (`%APPDATA%`) |
163    ///
164    /// Other paths can be configured via [`set_data_home`](Self::set_data_home).
165    ///
166    /// [XDG]: crate::os::unix::fs::HomeDirsExt
167    /// [Darwin]: crate::os::darwin::fs::HomeDirsExt
168    /// [Windows]: crate::os::windows::fs::HomeDirsExt
169    /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc
170    /// [`{FOLDERID_RoamingAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_roamingappdata
171    #[unstable(feature = "fs_home_dirs", issue = "162082")]
172    pub fn data_home(&self) -> Option<&Path> {
173        self.data.as_deref()
174    }
175
176    /// A base directory relative to which user-specific state files should be
177    /// stored.
178    ///
179    /// "State" files are data that should persist between application restarts,
180    /// but which is not important nor portable enough to the user to synchronize
181    /// between multiple systems like [data](Self::data_home) are. Common examples
182    /// include history (such as logs, recently used files, etc) and any current
183    /// state of the application that should be reused (such as view, layout, open
184    /// files, undo history, etc).
185    ///
186    /// This is the same directory for all applications. Applications should
187    /// use a subdirectory for application-specific state files.
188    ///
189    /// # Platform-specific behavior
190    ///
191    /// When constructed using platform-specific conventions, the value is:
192    ///
193    /// | OS | Path |
194    /// | -- | ---- |
195    /// | [XDG] (Linux) | `${XDG_STATE_HOME:-$HOME/.local/state}` |
196    /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) |
197    /// | [Windows] | [`{FOLDERID_LocalAppData}`] (`%LOCALAPPDATA%`) |
198    ///
199    /// Other paths can be configured via [`set_state_home`](Self::set_state_home).
200    ///
201    /// [XDG]: crate::os::unix::fs::HomeDirsExt
202    /// [Darwin]: crate::os::darwin::fs::HomeDirsExt
203    /// [Windows]: crate::os::windows::fs::HomeDirsExt
204    /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc
205    /// [`{FOLDERID_LocalAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_localappdata
206    #[unstable(feature = "fs_home_dirs", issue = "162082")]
207    pub fn state_home(&self) -> Option<&Path> {
208        self.state.as_deref()
209    }
210}
211
212impl MediaDirs {
213    /// Create a known user directory set with no known directories.
214    ///
215    /// This is useful with the builder `set_*` methods to create a `MediaDirs`
216    /// with exactly the directories you want, without any other defaults.
217    #[unstable(feature = "fs_media_dirs", issue = "162083")]
218    pub fn empty() -> Self {
219        Self {
220            desktop: None,
221            documents: None,
222            downloads: None,
223            music: None,
224            pictures: None,
225            videos: None,
226            extra: Default::default(),
227        }
228    }
229
230    /// The OS-recognized user "Desktop" directory, often the `Desktop`
231    /// folder in the user's home directory.
232    ///
233    /// As a media directory, this should typically be used as a default path
234    /// for file selection dialogs, not for automatically accessed file paths.
235    ///
236    /// # Platform-specific behavior
237    ///
238    /// When constructed using platform-specific conventions, the value is:
239    ///
240    /// | OS | Path |
241    /// | -- | ---- |
242    /// | [XDG] (Linux) | `xdg-user-dir DESKTOP` (`$HOME/Desktop`) |
243    /// | [Darwin] (macOS) | [`NSDesktopDirectory`] (`$HOME/Desktop`) |
244    /// | [Windows] | [`{FOLDERID_Desktop}`] (`%USERPROFILE%\Desktop`) |
245    ///
246    /// Other paths can be configured via [`set_desktop`](Self::set_desktop).
247    ///
248    /// [XDG]: crate::os::unix::fs::MediaDirsExt
249    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
250    /// [Windows]: crate::os::windows::fs::MediaDirsExt
251    /// [`NSDesktopDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/desktopdirectory?language=objc
252    /// [`{FOLDERID_Desktop}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_desktop
253    #[unstable(feature = "fs_media_dirs", issue = "162083")]
254    pub fn desktop(&self) -> Option<&Path> {
255        self.desktop.as_deref()
256    }
257
258    /// The OS-recognized user "Documents" directory, often the `Documents`
259    /// folder in the user's home directory.
260    ///
261    /// As a media directory, this should typically be used as a default path
262    /// for file selection dialogs, not for automatically accessed file paths.
263    ///
264    /// # Platform-specific behavior
265    ///
266    /// When constructed using platform-specific conventions, the value is:
267    ///
268    /// | OS | Path |
269    /// | -- | ---- |
270    /// | [XDG] (Linux) | `xdg-user-dir DOCUMENTS` (`$HOME/Documents`) |
271    /// | [Darwin] (macOS) | [`NSDocumentDirectory`] (`$HOME/Documents`) |
272    /// | [Windows] | [`{FOLDERID_Documents}`] (`%USERPROFILE%\Documents`) |
273    ///
274    /// Other paths can be configured via [`set_documents`](Self::set_documents).
275    ///
276    /// [XDG]: crate::os::unix::fs::MediaDirsExt
277    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
278    /// [Windows]: crate::os::windows::fs::MediaDirsExt
279    /// [`NSDocumentDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/documentdirectory?language=objc
280    /// [`{FOLDERID_Documents}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_documents
281    #[unstable(feature = "fs_media_dirs", issue = "162083")]
282    pub fn documents(&self) -> Option<&Path> {
283        self.documents.as_deref()
284    }
285
286    /// The OS-recognized user "Downloads" directory, often the `Downloads`
287    /// folder in the user's home directory.
288    ///
289    /// As a media directory, this should typically be used as a default path
290    /// for file selection dialogs, not for automatically accessed file paths.
291    ///
292    /// # Platform-specific behavior
293    ///
294    /// When constructed using platform-specific conventions, the value is:
295    ///
296    /// | OS | Path |
297    /// | -- | ---- |
298    /// | [XDG] (Linux) | `xdg-user-dir DOWNLOAD` (`$HOME/Downloads`) |
299    /// | [Darwin] (macOS) | [`NSDownloadsDirectory`] (`$HOME/Downloads`) |
300    /// | [Windows] | [`{FOLDERID_Downloads}`] (`%USERPROFILE%\Downloads`) |
301    ///
302    /// Other paths can be configured via [`set_downloads`](Self::set_downloads).
303    ///
304    /// [XDG]: crate::os::unix::fs::MediaDirsExt
305    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
306    /// [Windows]: crate::os::windows::fs::MediaDirsExt
307    /// [`NSDownloadsDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/downloadsdirectory?language=objc
308    /// [`{FOLDERID_Downloads}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_downloads
309    #[unstable(feature = "fs_media_dirs", issue = "162083")]
310    pub fn downloads(&self) -> Option<&Path> {
311        self.downloads.as_deref()
312    }
313
314    /// The OS-recognized user "Music" directory, often the `Music`
315    /// folder in the user's home directory.
316    ///
317    /// As a media directory, this should typically be used as a default path
318    /// for file selection dialogs, not for automatically accessed file paths.
319    ///
320    /// # Platform-specific behavior
321    ///
322    /// When constructed using platform-specific conventions, the value is:
323    ///
324    /// | OS | Path |
325    /// | -- | ---- |
326    /// | [XDG] (Linux) | `xdg-user-dir MUSIC` (`$HOME/Music`) |
327    /// | [Darwin] (macOS) | [`NSMusicDirectory`] (`$HOME/Music`) |
328    /// | [Windows] | [`{FOLDERID_Music}`] (`%USERPROFILE%\Music`) |
329    ///
330    /// Other paths can be configured via [`set_music`](Self::set_music).
331    ///
332    /// [XDG]: crate::os::unix::fs::MediaDirsExt
333    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
334    /// [Windows]: crate::os::windows::fs::MediaDirsExt
335    /// [`NSMusicDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/musicdirectory?language=objc
336    /// [`{FOLDERID_Music}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_music
337    #[unstable(feature = "fs_media_dirs", issue = "162083")]
338    pub fn music(&self) -> Option<&Path> {
339        self.music.as_deref()
340    }
341
342    /// The OS-recognized user "Pictures" directory, often the `Pictures`
343    /// folder in the user's home directory.
344    ///
345    /// As a media directory, this should typically be used as a default path
346    /// for file selection dialogs, not for automatically accessed file paths.
347    ///
348    /// # Platform-specific behavior
349    ///
350    /// When constructed using platform-specific conventions, the value is:
351    ///
352    /// | OS | Path |
353    /// | -- | ---- |
354    /// | [XDG] (Linux) | `xdg-user-dir PICTURES` (`$HOME/Pictures`) |
355    /// | [Darwin] (macOS) | [`NSPicturesDirectory`] (`$HOME/Pictures`) |
356    /// | [Windows] | [`{FOLDERID_Pictures}`] (`%USERPROFILE%\Pictures`) |
357    ///
358    /// Other paths can be configured via [`set_pictures`](Self::set_pictures).
359    ///
360    /// [XDG]: crate::os::unix::fs::MediaDirsExt
361    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
362    /// [Windows]: crate::os::windows::fs::MediaDirsExt
363    /// [`NSPicturesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/picturesdirectory?language=objc
364    /// [`{FOLDERID_Pictures}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_pictures
365    #[unstable(feature = "fs_media_dirs", issue = "162083")]
366    pub fn pictures(&self) -> Option<&Path> {
367        self.pictures.as_deref()
368    }
369
370    /// The OS-recognized user "Videos" directory, often the `Videos`
371    /// folder in the user's home directory.
372    ///
373    /// As a media directory, this should typically be used as a default path
374    /// for file selection dialogs, not for automatically accessed file paths.
375    ///
376    /// # Platform-specific behavior
377    ///
378    /// When constructed using platform-specific conventions, the value is:
379    ///
380    /// | OS | Path |
381    /// | -- | ---- |
382    /// | [XDG] (Linux) | `xdg-user-dir VIDEOS` (`$HOME/Videos`) |
383    /// | [Darwin] (macOS) | [`NSMoviesDirectory`] (`$HOME/Movies`) |
384    /// | [Windows] | [`{FOLDERID_Videos}`] (`%USERPROFILE%\Videos`) |
385    ///
386    /// Other paths can be configured via [`set_videos`](Self::set_videos).
387    ///
388    /// [XDG]: crate::os::unix::fs::MediaDirsExt
389    /// [Darwin]: crate::os::darwin::fs::MediaDirsExt
390    /// [Windows]: crate::os::windows::fs::MediaDirsExt
391    /// [`NSMoviesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/moviesdirectory?language=objc
392    /// [`{FOLDERID_Videos}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_videos
393    #[unstable(feature = "fs_media_dirs", issue = "162083")]
394    pub fn videos(&self) -> Option<&Path> {
395        self.videos.as_deref()
396    }
397}
398
399impl HomeDirs {
400    /// Set the path for [Self::cache_home].
401    ///
402    /// # Panics
403    ///
404    /// Panics if the provided path is not absolute.
405    #[unstable(feature = "fs_home_dirs", issue = "162082")]
406    pub fn set_cache_home(&mut self, path: PathBuf) -> &mut Self {
407        assert!(path.is_absolute(), "cache home directory path must be absolute");
408        self.cache = Some(path);
409        self
410    }
411
412    /// Set the path for [Self::config_home].
413    ///
414    /// # Panics
415    ///
416    /// Panics if the provided path is not absolute.
417    #[unstable(feature = "fs_home_dirs", issue = "162082")]
418    pub fn set_config_home(&mut self, path: PathBuf) -> &mut Self {
419        assert!(path.is_absolute(), "config home directory path must be absolute");
420        self.config = Some(path);
421        self
422    }
423
424    /// Set the path for [Self::data_home].
425    ///
426    /// # Panics
427    ///
428    /// Panics if the provided path is not absolute.
429    #[unstable(feature = "fs_home_dirs", issue = "162082")]
430    pub fn set_data_home(&mut self, path: PathBuf) -> &mut Self {
431        assert!(path.is_absolute(), "data home directory path must be absolute");
432        self.data = Some(path);
433        self
434    }
435
436    /// Set the path for [Self::state_home].
437    ///
438    /// # Panics
439    ///
440    /// Panics if the provided path is not absolute.
441    #[unstable(feature = "fs_home_dirs", issue = "162082")]
442    pub fn set_state_home(&mut self, path: PathBuf) -> &mut Self {
443        assert!(path.is_absolute(), "state home directory path must be absolute");
444        self.state = Some(path);
445        self
446    }
447}
448
449impl MediaDirs {
450    /// Set the path for [Self::desktop].
451    ///
452    /// # Panics
453    ///
454    /// Panics if the provided path is not absolute.
455    #[unstable(feature = "fs_media_dirs", issue = "162083")]
456    pub fn set_desktop(&mut self, path: PathBuf) -> &mut Self {
457        assert!(path.is_absolute(), "desktop directory path must be absolute");
458        self.desktop = Some(path);
459        self
460    }
461
462    /// Set the path for [Self::documents].
463    ///
464    /// # Panics
465    ///
466    /// Panics if the provided path is not absolute.
467    #[unstable(feature = "fs_media_dirs", issue = "162083")]
468    pub fn set_documents(&mut self, path: PathBuf) -> &mut Self {
469        assert!(path.is_absolute(), "documents directory path must be absolute");
470        self.documents = Some(path);
471        self
472    }
473
474    /// Set the path for [Self::downloads].
475    ///
476    /// # Panics
477    ///
478    /// Panics if the provided path is not absolute.
479    #[unstable(feature = "fs_media_dirs", issue = "162083")]
480    pub fn set_downloads(&mut self, path: PathBuf) -> &mut Self {
481        assert!(path.is_absolute(), "downloads directory path must be absolute");
482        self.downloads = Some(path);
483        self
484    }
485
486    /// Set the path for [Self::music].
487    ///
488    /// # Panics
489    ///
490    /// Panics if the provided path is not absolute.
491    #[unstable(feature = "fs_media_dirs", issue = "162083")]
492    pub fn set_music(&mut self, path: PathBuf) -> &mut Self {
493        assert!(path.is_absolute(), "music directory path must be absolute");
494        self.music = Some(path);
495        self
496    }
497
498    /// Set the path for [Self::pictures].
499    ///
500    /// # Panics
501    ///
502    /// Panics if the provided path is not absolute.
503    #[unstable(feature = "fs_media_dirs", issue = "162083")]
504    pub fn set_pictures(&mut self, path: PathBuf) -> &mut Self {
505        assert!(path.is_absolute(), "pictures directory path must be absolute");
506        self.pictures = Some(path);
507        self
508    }
509
510    /// Set the path for [Self::videos].
511    ///
512    /// # Panics
513    ///
514    /// Panics if the provided path is not absolute.
515    #[unstable(feature = "fs_media_dirs", issue = "162083")]
516    pub fn set_videos(&mut self, path: PathBuf) -> &mut Self {
517        assert!(path.is_absolute(), "videos directory path must be absolute");
518        self.videos = Some(path);
519        self
520    }
521}
522
523#[cfg(test)]
524mod tests {
525    use super::*;
526
527    fn test_dir(what: &str) -> PathBuf {
528        crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what)
529    }
530
531    #[test]
532    fn test_home_dirs_field_hookup_matches() {
533        let mut dirs = HomeDirs::empty();
534
535        assert_eq!(dirs.config_home(), None);
536        assert_eq!(dirs.data_home(), None);
537        assert_eq!(dirs.state_home(), None);
538        assert_eq!(dirs.cache_home(), None);
539
540        let config = test_dir("config");
541        let data = test_dir("data");
542        let state = test_dir("state");
543        let cache = test_dir("cache");
544
545        dirs.set_config_home(config.clone());
546        dirs.set_data_home(data.clone());
547        dirs.set_state_home(state.clone());
548        dirs.set_cache_home(cache.clone());
549
550        assert_eq!(dirs.config_home(), Some(config.as_ref()));
551        assert_eq!(dirs.data_home(), Some(data.as_ref()));
552        assert_eq!(dirs.state_home(), Some(state.as_ref()));
553        assert_eq!(dirs.cache_home(), Some(cache.as_ref()));
554    }
555
556    #[test]
557    fn test_media_dirs_field_hookup_matches() {
558        let mut dirs = MediaDirs::empty();
559
560        assert_eq!(dirs.desktop(), None);
561        assert_eq!(dirs.documents(), None);
562        assert_eq!(dirs.downloads(), None);
563        assert_eq!(dirs.music(), None);
564        assert_eq!(dirs.pictures(), None);
565        assert_eq!(dirs.videos(), None);
566
567        let desktop = test_dir("desktop");
568        let documents = test_dir("documents");
569        let downloads = test_dir("downloads");
570        let music = test_dir("music");
571        let pictures = test_dir("pictures");
572        let videos = test_dir("videos");
573
574        dirs.set_desktop(desktop.clone());
575        dirs.set_documents(documents.clone());
576        dirs.set_downloads(downloads.clone());
577        dirs.set_music(music.clone());
578        dirs.set_pictures(pictures.clone());
579        dirs.set_videos(videos.clone());
580
581        assert_eq!(dirs.desktop(), Some(desktop.as_ref()));
582        assert_eq!(dirs.documents(), Some(documents.as_ref()));
583        assert_eq!(dirs.downloads(), Some(downloads.as_ref()));
584        assert_eq!(dirs.music(), Some(music.as_ref()));
585        assert_eq!(dirs.pictures(), Some(pictures.as_ref()));
586        assert_eq!(dirs.videos(), Some(videos.as_ref()));
587    }
588}