paved 0.6.0

A simple platform agnostic path representation
Documentation
use std::ffi::OsString;

use crate::{PathPrefix, PathType, PavedAbsolutizeError, PavedPath};

impl PavedPath {
    /// Adds a directory to the path, this will be appended ***before*** the file if one should be set
    ///
    /// Performs light normalization by automatically resolving ".." and "." without touching the file system
    ///
    /// Will also resolve multiple directories within the same path, based on "/" and "\\", either one is considered a separation regardless of platform
    pub fn with_dir(mut self, dir: impl Into<OsString>) -> Self {
        self.push_dir(dir);
        self
    }

    /// Pushes all directories into the list of directories, wrapper around [`PavedPath::extend()`]
    ///
    /// Performs same normalization as [`PavedPath::push_dir`]
    pub fn with_dirs(mut self, dirs: impl IntoIterator<Item = impl Into<OsString>>) -> Self {
        self.push_dirs(dirs);
        self
    }

    /// Makes [`Self`] absolute based on a root.
    ///
    /// # Errors
    ///
    /// This function will return an error if [Self] is already absolute or root is relative.
    pub fn absolutize(mut self, root: &Self) -> Result<Self, PavedAbsolutizeError> {
        if self.is_absolute() {
            return Err(PavedAbsolutizeError::PathIsAbsolute);
        }
        if root.is_relative() {
            return Err(PavedAbsolutizeError::RootIsRelative);
        }

        if let Some(prefix) = root.get_prefix() {
            self.set_prefix(prefix.clone());
        }

        let dirs = self.directories;
        self.directories = Vec::new();
        self.push_dirs(root.get_dirs().clone()).push_dirs(dirs);

        self.set_type(PathType::Absolute);

        Ok(self)
    }

    /// Sets the file for the path, this will always be the last element and not followed by a trailing slash
    ///
    /// It is your duty to ensure the cleanliness of this file, it should ***never*** contain path separators!
    pub fn with_file(mut self, file: impl Into<OsString>) -> Self {
        self.set_file(file.into());
        self
    }

    /// Removes the file from the path
    pub fn without_file(mut self) -> Self {
        self.remove_file();
        self
    }

    /// Sets the path type to the new [`PathType`] specified, will change behavior of path building
    pub fn with_type(mut self, new_type: PathType) -> Self {
        self.set_type(new_type);
        self
    }

    /// Sets the path "drive" prefix for the path, this is only used for Windows style absolute paths, see also [`PathPrefix`]
    pub fn with_prefix(mut self, prefix: PathPrefix) -> Self {
        self.set_prefix(prefix);
        self
    }

    /// Removes the "drive" prefix from the path
    pub fn without_prefix(mut self) -> Self {
        self.remove_prefix();
        self
    }
}