paved 0.6.0

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

use crate::{PathPrefix, PathType, 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 push_dir(&mut self, dir: impl Into<OsString>) -> &mut Self {
        self.push_dir_raw(dir.into());

        self.rebuild_inner();
        self
    }

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

    /// Removes the last directory in the directory list, will not alter the file if one is set
    pub fn pop_dir(&mut self) -> Option<OsString> {
        self.directories.pop()
    }

    /// Replaces the internal list of directories with a new [`Vec<OsString>`], will ***not*** perform normalization
    ///
    /// It is your duty to ensure that this new vector is valid, if you want automatic normalization consider [`Self::push_dirs()`] or [`Self::push_dir()`] instead
    pub fn set_dirs(&mut self, dirs: impl IntoIterator<Item = impl Into<OsString>>) -> &mut Self {
        self.directories = dirs.into_iter().map(|d| d.into()).collect();

        self.rebuild_inner();
        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 set_file(&mut self, file: impl Into<OsString>) -> &mut Self {
        self.file = file.into().into();

        self.rebuild_inner();
        self
    }

    /// Removes the file from the path
    pub fn remove_file(&mut self) -> &mut Self {
        self.file = None;

        self.rebuild_inner();
        self
    }

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

        self.rebuild_inner();
        self
    }

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

        if cfg!(windows) {
            self.rebuild_inner();
        }
        self
    }

    /// Removes the "drive" prefix from the path
    pub fn remove_prefix(&mut self) -> &mut Self {
        self.path_prefix = None;

        if cfg!(windows) {
            self.rebuild_inner();
        }
        self
    }
}