doe 1.1.78

doe is a powerful Rust crate designed to enhance development workflow by providing an extensive collection of useful macros and utility functions. It not only simplifies common tasks but also offers convenient features for clipboard management,robust cryptographic functions,keyboard input, and mouse interaction.
Documentation
#[allow(warnings)]
///
///## useage of fs module
///```ignore
///fn main() {
///    use doe::*;
///    use doe::DebugPrint;
///    use doe::Str;
///    use std::ops::Deref;
///    // append data to file
///    append_data_to_file("demo.txt", "demo".as_bytes().to_vec()).unwrap();
///
///    // get all files and folders
///    walk_dir(".".to_path().deref()).unwrap().dprintln();
///
///    // get all folders
///    walk_dir_get_files(".".to_path().deref()).unwrap().dprintln();
///
///    // get all folders
///    walk_dir_get_folders(".".to_path().deref())
///        .unwrap()
///        .dprintln();
///
///    //move file the directory to a new directory
///    move_file(
///        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
///    )
///    .unwrap();
///
///    //copy file the directory to a new directory
///    copy_file(
///        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
///    )
///    .unwrap();
///    //move all files in the directory to a new directory
///    move_folder(
///        "/Users/ryanandrew/code/test/t1".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/t1".to_path().deref(),
///    )
///    .unwrap();
///
///    //copy all files in the directory to a new directory
///    copy_folder(
///        "/Users/ryanandrew/code/test/d1".to_path().deref(),
///        "/Users/ryanandrew/code/test/d2".to_path().deref(),
///    )
///    .unwrap();
///}
///```
pub mod fs {
    use std::ffi::OsStr;
    use std::fs::{self, File, Metadata, OpenOptions};
    use std::io::{self, Read, Seek, Write};
    use std::path::{Path, PathBuf};

    ///append data to file
    pub fn append_data_to_file<T: AsRef<[u8]>, P: AsRef<Path>>(path: P, data: T) -> io::Result<()> {
        let mut file = OpenOptions::new().create(true).append(true).open(path)?;
        file.write_all(data.as_ref())?;
        Ok(())
    }

    /// get all files
    pub fn walk_dir_get_files(path: impl ToString) -> io::Result<Vec<PathBuf>> {
        let path = path.to_string();
        let mut files = walk_dir(path)?;
        Ok(files.into_iter().filter(|s| s.is_file()).collect())
    }

    /// get all folders
    pub fn walk_dir_get_folders(path: impl ToString) -> io::Result<Vec<PathBuf>> {
        let path = path.to_string();
        let mut files = walk_dir(path)?;
        Ok(files.into_iter().filter(|s| s.is_dir()).collect())
    }

    /// get all files and folders
    pub fn walk_dir(path: impl ToString) -> io::Result<Vec<PathBuf>> {
        let path = path.to_string();
        let dir = Path::new(&path);
        let mut files = Vec::new();
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            let newpath = entry.path();
            if newpath.is_dir() {
                files.extend(walk_dir(&newpath.display())?);
                files.push(newpath);
            } else {
                files.push(newpath);
            }
        }
        Ok(files)
    }
    /// move all file in the directory to a new directory
    pub fn move_file(from: &Path, to: &Path) -> io::Result<()> {
        fs::rename(from, to)?;
        Ok(())
    }
    /// copy all file in the directory to a new directory
    pub fn copy_file(from: &Path, to: &Path) -> io::Result<()> {
        fs::copy(from, to)?;
        Ok(())
    }
    /// move all files in the directory to a new directory
    pub fn move_folder(from: &Path, to: &Path) -> io::Result<()> {
        fs::create_dir_all(to)?;
        let entries = fs::read_dir(from)?;
        for entry in entries {
            let entry = entry?;
            let source_path = entry.path();
            let file_name = entry.file_name();
            let target_path = to.join(file_name);
            // move
            fs::rename(source_path, target_path)?;
        }
        std::fs::remove_dir_all(from)?;

        Ok(())
    }
    /// Copy all files and directories in the directory to a new directory
    pub fn copy_folder(from: &Path, to: &Path) -> io::Result<()> {
        // Create the destination directory if it doesn't exist
        fs::create_dir_all(to)?;

        // Iterate over the entries in the source directory
        for entry in fs::read_dir(from)? {
            let entry = entry?;
            let entry_path = entry.path();

            // Get the destination path by joining the entry's file name with the destination directory
            let dest_path = to.join(entry.file_name());

            // Check if the entry is a file or a directory
            if entry_path.is_file() {
                // Copy the file to the destination directory
                fs::copy(&entry_path, &dest_path)?;
            } else if entry_path.is_dir() {
                // Recursively copy the directory to the destination directory
                copy_folder(&entry_path, &dest_path)?;
            }
        }
        Ok(())
    }
    ///get Home directory
    /// ```rust
    ///     use doe::home_dir;
    ///     use doe::DebugPrint;
    ///      home_dir().dprintln();
    /// ```
    pub fn home_dir() -> Option<PathBuf> {
        if let Some(home_dir) = std::env::var("HOME").ok().map(PathBuf::from) {
            Some(home_dir)
        } else {
            None
        }
    }

    /// Returns metadata for a file (follows symlinks).
    ///
    /// Equivalent to [`std::fs::metadata`] with better error messages.
    pub fn metadata<P: AsRef<Path>>(path: P) -> Result<Metadata, String> {
        let path = path.as_ref();
        std::fs::metadata(path).map_err(|r| format!("failed to get metadata for"))
    }

    /// Equivalent to [`write()`], but does not write anything if the file contents
    /// are identical to the given contents.
    pub fn write_if_changed<P: AsRef<Path>, C: AsRef<[u8]>>(
        path: P,
        contents: C,
    ) -> Result<(), String> {
        let contents = contents.as_ref();
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();
        let mut orig = Vec::new();
        f.read_to_end(&mut orig).unwrap();
        if orig != contents {
            f.set_len(0).unwrap();
            f.seek(io::SeekFrom::Start(0)).unwrap();
            f.write_all(contents).unwrap();
        }
        Ok(())
    }

    /// Converts a path to UTF-8 bytes.
    pub fn path_to_bytes(path: &Path) -> Result<&[u8], String> {
        #[cfg(unix)]
        {
            use std::os::unix::prelude::*;
            Ok(path.as_os_str().as_bytes())
        }
        #[cfg(windows)]
        {
            match path.as_os_str().to_str() {
                Some(s) => Ok(s.as_bytes()),
                None => Err(format!("invalid non-unicode path: {}", path.display())),
            }
        }
    }

    /// Converts UTF-8 bytes to a path.
    pub fn bytes_to_path(bytes: &[u8]) -> Result<PathBuf, String> {
        #[cfg(unix)]
        {
            use std::os::unix::prelude::*;
            Ok(PathBuf::from(OsStr::from_bytes(bytes)))
        }
        #[cfg(windows)]
        {
            use std::str;
            match str::from_utf8(bytes) {
                Ok(s) => Ok(PathBuf::from(s)),
                Err(..) => Err(format!("invalid non-unicode path")),
            }
        }
    }

    pub fn set_not_readonly(p: &Path) -> io::Result<bool> {
        let mut perms = p.metadata()?.permissions();
        if !perms.readonly() {
            return Ok(false);
        }
        perms.set_readonly(false);
        fs::set_permissions(p, perms)?;
        Ok(true)
    }
}
pub use fs::*;