diff options
Diffstat (limited to 'src/path.rs')
-rw-r--r-- | src/path.rs | 319 |
1 files changed, 0 insertions, 319 deletions
diff --git a/src/path.rs b/src/path.rs deleted file mode 100644 index 7df10b2..0000000 --- a/src/path.rs +++ /dev/null @@ -1,319 +0,0 @@ -/* - * We implement most aspects of paths independently, not relying on - * std::path, on the theory that path syntax is such an important part of a - * shell that it doesn't make sense to try to integrate with non-Unix syntaxes. - * However, we do use std::path to print individual path components, in order - * to get the benefit of its functionality for handling non-Unicode filenames. - */ - -#![forbid(unsafe_code)] -use crate::path::prelude::*; - -use std::str::FromStr; - - -lalrpop_mod!(pub parser, "/path/parser.rs"); -pub mod error; -pub mod prelude; - - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub struct AbsoluteDirectoryPath { - directory_names: Vec<DirectoryName>, -} - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub struct AbsoluteFilePath { - directory_names: Vec<DirectoryName>, - file_name: FileName, -} - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub struct FileName(String); - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub struct DirectoryName(String); - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub struct GenericPath { - components: Vec<GenericPathComponent>, - starts_with_slash: bool, - ends_with_slash: bool, -} - -#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] -pub enum GenericPathComponent { - FileOrDirectoryName(String), - CurrentDirectory, - ParentDirectory, -} - - -impl std::fmt::Display for AbsoluteDirectoryPath { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for directory_name in &self.directory_names { - f.write_str("/")?; - directory_name.fmt(f)?; - } - - f.write_str("/")?; - - Ok(()) - } -} - - -impl std::fmt::Display for AbsoluteFilePath { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for directory_name in &self.directory_names { - f.write_str("/")?; - directory_name.fmt(f)?; - } - - f.write_str("/")?; - - self.file_name.fmt(f)?; - - Ok(()) - } -} - - -impl std::fmt::Display for FileName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - FileName(name) => { - let std_path = std::path::Path::new(&name); - f.write_fmt(format_args!("{}", std_path.display()))?; - }, - } - - Ok(()) - } -} - - -impl std::fmt::Display for DirectoryName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - DirectoryName(name) => { - let std_path = std::path::Path::new(&name); - f.write_fmt(format_args!("{}", std_path.display()))?; - }, - } - - Ok(()) - } -} - - -impl std::fmt::Display for GenericPath { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.starts_with_slash { - f.write_str("/")?; - } - - let mut is_first = true; - for component in &self.components { - if !is_first { - f.write_str("/")?; - } - - component.fmt(f)?; - - is_first = false; - } - - if self.ends_with_slash { - f.write_str("/")?; - } - - Ok(()) - } -} - - -impl std::fmt::Display for GenericPathComponent { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - GenericPathComponent::FileOrDirectoryName(name) => { - let std_path = std::path::Path::new(&name); - f.write_fmt(format_args!("{}", std_path.display()))?; - }, - GenericPathComponent::CurrentDirectory => { - f.write_str(".")?; - }, - GenericPathComponent::ParentDirectory => { - f.write_str("..")?; - }, - } - - Ok(()) - } -} - - -impl FromStr for FileName { - type Err = FileNameError; - - fn from_str(input: &str) -> std::result::Result<Self, Self::Err> { - if input.find('/').is_some() { - Err(FileNameError::ContainsSlash(input.to_string())) - } else { - Ok(FileName(input.to_string())) - } - } -} - - -impl FromStr for DirectoryName { - type Err = DirectoryNameError; - - fn from_str(input: &str) -> std::result::Result<Self, Self::Err> { - if input.find('/').is_some() { - Err(DirectoryNameError::ContainsSlash(input.to_string())) - } else { - Ok(DirectoryName(input.to_string())) - } - } -} - - -impl FromStr for GenericPathComponent { - type Err = PathError; - - fn from_str(input: &str) -> std::result::Result<Self, Self::Err> { - parser::PathComponentParser::new().parse(input).map_err( - |e| PathError::Parse(e.to_string())) - } -} - - -impl AbsoluteDirectoryPath { - pub fn to_sys_path(&self) -> std::path::PathBuf { - let mut result = std::path::PathBuf::new(); - result.push(format!("{}", self)); - result - } - - pub fn concat_file_name(&self, file_name: &FileName) -> AbsoluteFilePath { - AbsoluteFilePath { - directory_names: self.directory_names.clone(), - file_name: file_name.clone(), - } - } -} - - -impl AbsoluteFilePath { - pub fn to_sys_path(&self) -> std::path::PathBuf { - let mut result = std::path::PathBuf::new(); - result.push(format!("{}", self)); - result - } -} - - -pub fn parse_path_list(path_list: &str) - -> Result<Vec<AbsoluteDirectoryPath>> -{ - match parser::PathListParser::new().parse(path_list) { - Ok(parsed_paths) => { - let mut result = Vec::new(); - for generic_path in parsed_paths { - let path = absolute_directory_path(generic_path)?; - result.push(path); - } - Ok(result) - }, - Err(original_error) => { - match parser::PathListAllowingEmptyPathsParser::new() - .parse(path_list) - { - Ok(_) => { - Err(PathError::PathListHasEmptyComponents(path_list.to_string())) - }, - Err(_) => { - Err(PathError::Parse(original_error.to_string())) - }, - } - }, - } -} - - -pub fn absolute_directory_path(generic_path: GenericPath) - -> Result<AbsoluteDirectoryPath> -{ - if !generic_path.starts_with_slash { - return Err(PathError::PathLexicallyRelative(generic_path)); - } - - let mut flattened_components = Vec::new(); - for component in &generic_path.components { - match component { - GenericPathComponent::CurrentDirectory => { }, - GenericPathComponent::ParentDirectory => { - if flattened_components.len() > 0 { - flattened_components.pop(); - } else { - return Err(PathError::PathLexicallyInvalid(generic_path)); - } - }, - GenericPathComponent::FileOrDirectoryName(name) => { - flattened_components.push(DirectoryName(name.to_string())); - }, - } - } - - Ok(AbsoluteDirectoryPath { - directory_names: flattened_components, - }) -} - - -pub fn absolute_file_path(generic_path: GenericPath) - -> Result<AbsoluteFilePath> -{ - if !generic_path.starts_with_slash { - return Err(PathError::PathLexicallyRelative(generic_path)); - } - - if generic_path.ends_with_slash { - return Err(PathError::PathLexicallyDirectory(generic_path)); - } - - let mut iterator = generic_path.components.iter(); - - let file_name = match iterator.next_back() { - Some(GenericPathComponent::FileOrDirectoryName(name)) => { - FileName(name.to_string()) - } - _ => { - return Err(PathError::PathLexicallyInvalid(generic_path)); - } - }; - - let mut flattened_components = Vec::new(); - for component in &generic_path.components { - match component { - GenericPathComponent::CurrentDirectory => { }, - GenericPathComponent::ParentDirectory => { - if flattened_components.len() > 0 { - flattened_components.pop(); - } else { - return Err(PathError::PathLexicallyInvalid(generic_path)); - } - }, - GenericPathComponent::FileOrDirectoryName(name) => { - flattened_components.push(DirectoryName(name.to_string())); - }, - } - } - - Ok(AbsoluteFilePath { - directory_names: flattened_components, - file_name: file_name, - }) -} - |