fspp 2.2.1

Filesystem++ : Access the filesystem in a cleaner, easier way.
Documentation
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};

#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// The type of a path: (File, Directory, Invalid)
pub enum PathType {
    File,
    Directory,
    Invalid,
}

#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// Path to a file or folder
///
/// When using Path::new(), the function will automatically convert forward/backward slashes depending on the OS
pub struct Path {
    path: String,
}

impl Path {
    /// What is the filesystem split character for the current OS?
    #[cfg(target_os = "windows")]
    pub const SPLIT_CHAR: char = '\\';

    #[cfg(not(target_os = "windows"))]
    pub const SPLIT_CHAR: char = '/';

    /// What is not the filesystem split character for the current OS?
    #[cfg(target_os = "windows")]
    pub const NOT_SPLIT_CHAR: char = '/';

    #[cfg(not(target_os = "windows"))]
    pub const NOT_SPLIT_CHAR: char = '\\';

    /// Create a new path
    pub fn new(user_path: &str) -> Self {
        let mut path = user_path.to_string();

        if path.ends_with(Self::SPLIT_CHAR) {
            path = path[0..path.len() - 1].to_string();
        }

        path = path.replace(
            Self::NOT_SPLIT_CHAR.to_string().as_str(),
            Self::SPLIT_CHAR.to_string().as_str(),
        );

        return Self {
            path,
        };
    }

    /// If the path does infact exist, the return value will be true, else, false
    pub fn exists(&self) -> bool {
        return std::path::Path::new(self.path.as_str()).exists();
    }

    /// Get the base name of a path
    ///
    /// # Examples:
    /// ```rust
    /// use fspp::*;
    ///
    /// let path = Path::new("folder1/folder2/folder3/hello.txt");
    ///
    /// assert!(path.basename() == "hello.txt");
    /// ```
    pub fn basename(&self) -> String {
        let mut segments: Vec<String> = Vec::new();

        for i in self.to_string().split(Self::SPLIT_CHAR) {
            segments.push(i.to_string());
        }

        return segments[segments.len() - 1].to_string();
    }

    /// Get the parent path of a path
    ///
    /// # Examples:
    /// ```rust
    /// use fspp::*;
    ///
    /// let path = Path::new("folder1/folder2/folder3/hello.txt");
    ///
    /// assert!(path.parent_path().to_string() == "folder1/folder2/folder3");
    /// ```
    pub fn parent_path(&self) -> Self {
        return Self::new(&self.to_string().replace(&format!("{sc}{}", self.basename(), sc = Self::SPLIT_CHAR), ""));
    }

    /// Get the path type for a path
    ///
    /// # Examples:
    /// ```rust
    /// use fspp::*;
    ///
    /// let path = Path::new("hello.txt");
    ///
    /// match path.path_type() {
    ///     PathType::File => println!("hello.txt is a file!"),
    ///     PathType::Directory => println!("hello.txt is... a directory!?"),
    ///     PathType::Invalid => println!("hello.txt doesn't exist!"),
    /// };
    /// ```
    pub fn path_type(&self) -> PathType {
        if self.exists() == false {
            return PathType::Invalid;
        }

        if std::path::Path::new(self.to_string().as_str()).is_file() {
            return PathType::File;
        }

        else {
            return PathType::Directory;
        }
    }

    /// Add path segments to an existing path
    ///
    /// # Examples:
    /// ```rust
    /// use fspp::*;
    ///
    /// let mut path = Path::new("folder1/folder2");
    /// path = path.add(&Path::new("folder3/hello.txt")); // The function is smart enough to fill in the missing '/' at the beginning.
    ///
    /// assert!(path.to_string() == "folder1/folder2/folder3/hello.txt");
    /// ```
    pub fn add(&self, extra: &Self) -> Self {
        if extra.to_string().starts_with(Self::SPLIT_CHAR) == false {
            return Self::new(&format!("{}/{}", self.to_string(), extra.to_string()));
        }

        else {
            return Self::new(&format!("{}{}", self.to_string(), extra.to_string()));
        }
    }

    /// Add path segments (&str) to an existing path
    ///
    /// # Examples:
    /// ```rust
    /// use fspp::*;
    ///
    /// let mut path = Path::new("folder1/folder2");
    /// path = path.add_str("folder3/hello.txt"); // The function is smart enough to fill in the missing '/' at the beginning.
    ///
    /// assert!(path.to_string() == "folder1/folder2/folder3/hello.txt");
    /// ```
    pub fn add_str(&self, extra: &str) -> Self {
        return self.add(&Path::new(extra));
    }
}

impl ToString for Path {
    /// Convert path to string to be printed out or something
    fn to_string(&self) -> String {
        return self.path.to_string();
    }
}