1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::common::{AppDataType, AppDirsError, AppInfo};
use std::fs;
use std::path::PathBuf;
use crate::utils;

#[cfg(target_os="macos")]
mod platform {
    mod macos;
    pub use self::macos::*;
}
#[cfg(all(unix, not(target_os="macos"), not(target_os="android")))]
mod platform {
    mod unix;
    pub use self::unix::*;
}
#[cfg(windows)]
mod platform {
    mod windows;
    pub use self::windows::*;
}
#[cfg(not(any(windows, unix, target_os="macos",)))]
mod platform {
    mod unknown;
    pub use self::unknown::*;
}
#[cfg(target_os="android")]
mod platform {
    mod android;
    pub use self::android::*;
}

/// Creates (if necessary) and returns path to **app-specific** data
/// **subdirectory** for provided data type and subdirectory path.
///
/// The `path` parameter should be a valid relative path separated by
/// **forward slashes** (`/`).
///
/// If the directory structure does not exist, this function will recursively
/// create the full hierarchy. Therefore, a result of `Ok` guarantees that the
/// returned path exists.
pub fn app_dir(t: AppDataType, app: &AppInfo, path: &str) -> Result<PathBuf, AppDirsError> {
    let path = get_app_dir(t, app, &path)?;
    match fs::create_dir_all(&path) {
        Ok(..) => Ok(path),
        Err(e) => Err(e.into()),
    }
}

/// Returns (but **does not create**) path to **app-specific** data
/// **subdirectory** for provided data type and subdirectory path.
///
/// The `path` parameter should be a valid relative path separated by
/// **forward slashes** (`/`).
///
/// A result of `Ok` means that we determined where the data SHOULD go, but
/// it DOES NOT guarantee that the directory actually exists. (See
/// [`app_dir`](fn.app_dir.html).)
pub fn get_app_dir(t: AppDataType, app: &AppInfo, path: &str) -> Result<PathBuf, AppDirsError> {
    if app.author.len() == 0 || app.name.len() == 0 {
        return Err(AppDirsError::InvalidAppInfo);
    }
    get_app_root(t, app).map(|mut root| {
        for component in path.split("/").filter(|s| s.len() > 0) {
            root.push(utils::sanitized(component));
        }
        root
    })
}

/// Creates (if necessary) and returns path to **app-specific** data
/// directory for provided data type.
///
/// If the directory structure does not exist, this function will recursively
/// create the full hierarchy. Therefore, a result of `Ok` guarantees that the
/// returned path exists.
pub fn app_root(t: AppDataType, app: &AppInfo) -> Result<PathBuf, AppDirsError> {
    let path = get_app_root(t, app)?;
    match fs::create_dir_all(&path) {
        Ok(..) => Ok(path),
        Err(e) => Err(e.into()),
    }
}

/// Returns (but **does not create**) path to **app-specific** data directory
/// for provided data type.
///
/// A result of `Ok` means that we determined where the data SHOULD go, but
/// it DOES NOT guarantee that the directory actually exists. (See
/// [`app_root`](fn.app_root.html).)
pub fn get_app_root(t: AppDataType, app: &AppInfo) -> Result<PathBuf, AppDirsError> {
    if app.author.len() == 0 || app.name.len() == 0 {
        return Err(AppDirsError::InvalidAppInfo);
    }
    get_data_root(t).map(|mut root| {
        if platform::USE_AUTHOR {
            root.push(utils::sanitized(app.author));
        }
        root.push(utils::sanitized(app.name));
        root
    })
}

/// Creates (if necessary) and returns path to **top-level** data directory
/// for provided data type.
///
/// If the directory structure does not exist, this function will recursively
/// create the full hierarchy. Therefore, a result of `Ok` guarantees that the
/// returned path exists.
pub fn data_root(t: AppDataType) -> Result<PathBuf, AppDirsError> {
    let path = platform::get_app_dir(t)?;
    match fs::create_dir_all(&path) {
        Ok(..) => Ok(path),
        Err(e) => Err(e.into()),
    }
}

/// Returns (but **does not create**) path to **top-level** data directory for
/// provided data type.
///
/// A result of `Ok` means that we determined where the data SHOULD go, but
/// it DOES NOT guarantee that the directory actually exists. (See
/// [`data_root`](fn.data_root.html).)
pub fn get_data_root(t: AppDataType) -> Result<PathBuf, AppDirsError> {
    platform::get_app_dir(t)
}