133d722a9Sopenharmony_ci#![allow(dead_code)]
233d722a9Sopenharmony_ci
333d722a9Sopenharmony_ciuse std::error::Error as StdError;
433d722a9Sopenharmony_ciuse std::fmt::{self, Display};
533d722a9Sopenharmony_ciuse std::io::{self, Read};
633d722a9Sopenharmony_ciuse std::path::{Path, PathBuf};
733d722a9Sopenharmony_ci
833d722a9Sopenharmony_cipub(crate) type Result<T> = std::result::Result<T, Error>;
933d722a9Sopenharmony_ci
1033d722a9Sopenharmony_ci#[derive(Debug)]
1133d722a9Sopenharmony_cipub(crate) struct Error {
1233d722a9Sopenharmony_ci    source: Option<io::Error>,
1333d722a9Sopenharmony_ci    message: String,
1433d722a9Sopenharmony_ci}
1533d722a9Sopenharmony_ci
1633d722a9Sopenharmony_ciimpl Error {
1733d722a9Sopenharmony_ci    pub fn kind(&self) -> io::ErrorKind {
1833d722a9Sopenharmony_ci        match &self.source {
1933d722a9Sopenharmony_ci            Some(io_error) => io_error.kind(),
2033d722a9Sopenharmony_ci            None => io::ErrorKind::Other,
2133d722a9Sopenharmony_ci        }
2233d722a9Sopenharmony_ci    }
2333d722a9Sopenharmony_ci}
2433d722a9Sopenharmony_ci
2533d722a9Sopenharmony_ciimpl Display for Error {
2633d722a9Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2733d722a9Sopenharmony_ci        formatter.write_str(&self.message)
2833d722a9Sopenharmony_ci    }
2933d722a9Sopenharmony_ci}
3033d722a9Sopenharmony_ci
3133d722a9Sopenharmony_ciimpl StdError for Error {
3233d722a9Sopenharmony_ci    fn source(&self) -> Option<&(dyn StdError + 'static)> {
3333d722a9Sopenharmony_ci        let source = self.source.as_ref()?;
3433d722a9Sopenharmony_ci        Some(source)
3533d722a9Sopenharmony_ci    }
3633d722a9Sopenharmony_ci}
3733d722a9Sopenharmony_ci
3833d722a9Sopenharmony_cimacro_rules! err {
3933d722a9Sopenharmony_ci    ($io_error:expr, $fmt:expr $(, $path:expr)* $(,)?) => {
4033d722a9Sopenharmony_ci        Err(Error {
4133d722a9Sopenharmony_ci            source: Option::from($io_error),
4233d722a9Sopenharmony_ci            message: format!($fmt $(, $path.display())*),
4333d722a9Sopenharmony_ci        })
4433d722a9Sopenharmony_ci    }
4533d722a9Sopenharmony_ci}
4633d722a9Sopenharmony_ci
4733d722a9Sopenharmony_cipub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64> {
4833d722a9Sopenharmony_ci    let from = from.as_ref();
4933d722a9Sopenharmony_ci    let to = to.as_ref();
5033d722a9Sopenharmony_ci    match std::fs::copy(from, to) {
5133d722a9Sopenharmony_ci        Ok(n) => Ok(n),
5233d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to copy `{}` -> `{}`", from, to),
5333d722a9Sopenharmony_ci    }
5433d722a9Sopenharmony_ci}
5533d722a9Sopenharmony_ci
5633d722a9Sopenharmony_cipub(crate) fn create_dir_all(path: impl AsRef<Path>) -> Result<()> {
5733d722a9Sopenharmony_ci    let path = path.as_ref();
5833d722a9Sopenharmony_ci    match std::fs::create_dir_all(path) {
5933d722a9Sopenharmony_ci        Ok(()) => Ok(()),
6033d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to create directory `{}`", path),
6133d722a9Sopenharmony_ci    }
6233d722a9Sopenharmony_ci}
6333d722a9Sopenharmony_ci
6433d722a9Sopenharmony_cipub(crate) fn current_dir() -> Result<PathBuf> {
6533d722a9Sopenharmony_ci    match std::env::current_dir() {
6633d722a9Sopenharmony_ci        Ok(dir) => Ok(dir),
6733d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to determine current directory"),
6833d722a9Sopenharmony_ci    }
6933d722a9Sopenharmony_ci}
7033d722a9Sopenharmony_ci
7133d722a9Sopenharmony_cipub(crate) fn exists(path: impl AsRef<Path>) -> bool {
7233d722a9Sopenharmony_ci    let path = path.as_ref();
7333d722a9Sopenharmony_ci    // If path is a symlink, this returns true, regardless of whether the
7433d722a9Sopenharmony_ci    // symlink points to a path that exists.
7533d722a9Sopenharmony_ci    std::fs::symlink_metadata(path).is_ok()
7633d722a9Sopenharmony_ci}
7733d722a9Sopenharmony_ci
7833d722a9Sopenharmony_cipub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
7933d722a9Sopenharmony_ci    let path = path.as_ref();
8033d722a9Sopenharmony_ci    match std::fs::read(path) {
8133d722a9Sopenharmony_ci        Ok(string) => Ok(string),
8233d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to read file `{}`", path),
8333d722a9Sopenharmony_ci    }
8433d722a9Sopenharmony_ci}
8533d722a9Sopenharmony_ci
8633d722a9Sopenharmony_cipub(crate) fn read_stdin() -> Result<Vec<u8>> {
8733d722a9Sopenharmony_ci    let mut bytes = Vec::new();
8833d722a9Sopenharmony_ci    match io::stdin().read_to_end(&mut bytes) {
8933d722a9Sopenharmony_ci        Ok(_len) => Ok(bytes),
9033d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to read input from stdin"),
9133d722a9Sopenharmony_ci    }
9233d722a9Sopenharmony_ci}
9333d722a9Sopenharmony_ci
9433d722a9Sopenharmony_cipub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
9533d722a9Sopenharmony_ci    let path = path.as_ref();
9633d722a9Sopenharmony_ci    match std::fs::remove_file(path) {
9733d722a9Sopenharmony_ci        Ok(()) => Ok(()),
9833d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to remove file `{}`", path),
9933d722a9Sopenharmony_ci    }
10033d722a9Sopenharmony_ci}
10133d722a9Sopenharmony_ci
10233d722a9Sopenharmony_cipub(crate) fn remove_dir(path: impl AsRef<Path>) -> Result<()> {
10333d722a9Sopenharmony_ci    let path = path.as_ref();
10433d722a9Sopenharmony_ci    match std::fs::remove_dir(path) {
10533d722a9Sopenharmony_ci        Ok(()) => Ok(()),
10633d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to remove directory `{}`", path),
10733d722a9Sopenharmony_ci    }
10833d722a9Sopenharmony_ci}
10933d722a9Sopenharmony_ci
11033d722a9Sopenharmony_cifn symlink<'a>(
11133d722a9Sopenharmony_ci    original: &'a Path,
11233d722a9Sopenharmony_ci    link: &'a Path,
11333d722a9Sopenharmony_ci    fun: fn(&'a Path, &'a Path) -> io::Result<()>,
11433d722a9Sopenharmony_ci) -> Result<()> {
11533d722a9Sopenharmony_ci    match fun(original, link) {
11633d722a9Sopenharmony_ci        Ok(()) => Ok(()),
11733d722a9Sopenharmony_ci        Err(e) => err!(
11833d722a9Sopenharmony_ci            e,
11933d722a9Sopenharmony_ci            "Failed to create symlink `{}` pointing to `{}`",
12033d722a9Sopenharmony_ci            link,
12133d722a9Sopenharmony_ci            original,
12233d722a9Sopenharmony_ci        ),
12333d722a9Sopenharmony_ci    }
12433d722a9Sopenharmony_ci}
12533d722a9Sopenharmony_ci
12633d722a9Sopenharmony_cipub(crate) fn symlink_fail(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
12733d722a9Sopenharmony_ci    err!(
12833d722a9Sopenharmony_ci        None,
12933d722a9Sopenharmony_ci        "Failed to create symlink `{}` pointing to `{}`",
13033d722a9Sopenharmony_ci        link.as_ref(),
13133d722a9Sopenharmony_ci        original.as_ref(),
13233d722a9Sopenharmony_ci    )
13333d722a9Sopenharmony_ci}
13433d722a9Sopenharmony_ci
13533d722a9Sopenharmony_ci#[cfg(unix)]
13633d722a9Sopenharmony_ci#[allow(unused_imports)]
13733d722a9Sopenharmony_cipub(crate) use self::symlink_file as symlink_dir;
13833d722a9Sopenharmony_ci
13933d722a9Sopenharmony_ci#[cfg(not(any(unix, windows)))]
14033d722a9Sopenharmony_ci#[allow(unused_imports)]
14133d722a9Sopenharmony_cipub(crate) use self::symlink_fail as symlink_dir;
14233d722a9Sopenharmony_ci
14333d722a9Sopenharmony_ci#[cfg(unix)]
14433d722a9Sopenharmony_cipub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
14533d722a9Sopenharmony_ci    symlink(original.as_ref(), link.as_ref(), std::os::unix::fs::symlink)
14633d722a9Sopenharmony_ci}
14733d722a9Sopenharmony_ci
14833d722a9Sopenharmony_ci#[cfg(windows)]
14933d722a9Sopenharmony_cipub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
15033d722a9Sopenharmony_ci    symlink(
15133d722a9Sopenharmony_ci        original.as_ref(),
15233d722a9Sopenharmony_ci        link.as_ref(),
15333d722a9Sopenharmony_ci        std::os::windows::fs::symlink_file,
15433d722a9Sopenharmony_ci    )
15533d722a9Sopenharmony_ci}
15633d722a9Sopenharmony_ci
15733d722a9Sopenharmony_ci#[cfg(windows)]
15833d722a9Sopenharmony_cipub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
15933d722a9Sopenharmony_ci    symlink(
16033d722a9Sopenharmony_ci        original.as_ref(),
16133d722a9Sopenharmony_ci        link.as_ref(),
16233d722a9Sopenharmony_ci        std::os::windows::fs::symlink_dir,
16333d722a9Sopenharmony_ci    )
16433d722a9Sopenharmony_ci}
16533d722a9Sopenharmony_ci
16633d722a9Sopenharmony_cipub(crate) fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {
16733d722a9Sopenharmony_ci    let path = path.as_ref();
16833d722a9Sopenharmony_ci    match std::fs::write(path, contents) {
16933d722a9Sopenharmony_ci        Ok(()) => Ok(()),
17033d722a9Sopenharmony_ci        Err(e) => err!(e, "Failed to write file `{}`", path),
17133d722a9Sopenharmony_ci    }
17233d722a9Sopenharmony_ci}
173