pub mod libpath {
pub mod util {
pub mod common {
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use fastparse::fastparse::types::PositionalSlice as PoSl;
#[derive(Debug)]
#[derive(Eq, PartialEq)]
pub struct ClassificationResult {
pub Input : PoSl,
pub FullPath : PoSl,
pub Prefix : PoSl,
pub Location : PoSl,
pub Root : PoSl,
pub Directory : PoSl,
pub NumDirectoryParts : usize,
pub NumDotsDirectoryParts : usize,
pub EntryName : PoSl,
pub Stem : PoSl,
pub Extension : PoSl,
pub FirstInvalid : PoSl,
}
impl ClassificationResult {
pub fn empty() -> Self {
Self {
Input : PoSl::empty(),
FullPath : PoSl::empty(),
Prefix : PoSl::empty(),
Location : PoSl::empty(),
Root : PoSl::empty(),
Directory : PoSl::empty(),
NumDirectoryParts : 0usize,
NumDotsDirectoryParts : 0usize,
EntryName : PoSl::empty(),
Stem : PoSl::empty(),
Extension : PoSl::empty(),
FirstInvalid : PoSl::empty(),
}
}
}
#[cfg(test)]
mod tests {
#![allow(non_snake_case)]
}
}
pub mod unix {
use super::common::ClassificationResult;
use fastparse::fastparse::types::PositionalSlice as PoSl;
pub mod classification_flags {
pub const IGNORE_SLASH_RUNS : i32 = 0x00000001;
pub const IGNORE_INVALID_CHARS : i32 = 0x00000002;
pub const RECOGNISE_TILDE_HOME : i32 = 0x00000004;
}
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Classification {
InvalidSlashRuns = -3,
InvalidChars = -2,
Invalid = -1,
Unknown,
Empty,
Relative,
SlashRooted,
_Reserved1,
_Reserved2,
_Reserved3,
_Reserved4,
HomeRooted,
}
#[allow(clippy::collapsible_if)]
pub fn path_classify(
path : &str,
parse_flags : i32,
) -> (
Classification, // classification
ClassificationResult, // classification_result
) {
if path.is_empty() {
return (
Classification::Empty,
ClassificationResult::empty(),
);
}
let mut cr = ClassificationResult::empty();
cr.Input = PoSl::new(0, path.len());
let (cl, root, path_root_stripped) = classify_root_(path, parse_flags);
cr.Root = PoSl::new(0, root.len());
let last_slash = find_last_slash_(path_root_stripped.substring_of(path));
match last_slash {
Some(index) => {
let dir_len = index + 1;
cr.Directory = PoSl::new(root.len(), dir_len);
let (num_parts, num_dir_parts) =
count_directory_parts_(cr.Directory.substring_of(path), parse_flags);
cr.NumDirectoryParts = num_parts;
cr.NumDotsDirectoryParts = num_dir_parts;
cr.EntryName = PoSl::new(root.len() + dir_len, path_root_stripped.len() - dir_len);
},
None => {
cr.Directory = PoSl::new(root.len(), 0);
cr.EntryName = PoSl::new(root.len(), path_root_stripped.len());
},
}
if cr.EntryName.is_empty() {
cr.Stem = cr.EntryName;
cr.Extension = cr.EntryName;
} else {
let last_entry_dot = cr.EntryName.substring_of(path).rfind('.');
match last_entry_dot {
Some(index) => {
let mut is_dots = false;
if !is_dots && 1 == cr.EntryName.len() {
is_dots = true;
}
if !is_dots {
if 2 == cr.EntryName.len() {
if ".." == cr.EntryName.substring_of(path) {
is_dots = true;
}
}
}
if is_dots {
cr.Stem = cr.EntryName;
cr.Extension = PoSl::new(cr.EntryName.len(), 0);
} else {
cr.Stem = PoSl::new(cr.EntryName.offset, index);
cr.Extension = PoSl::new(cr.EntryName.offset + index, cr.EntryName.len() - index);
}
},
None => {
cr.Stem = cr.EntryName;
cr.Extension = PoSl::new(cr.EntryName.offset + cr.EntryName.len(), 0);
},
}
}
cr.Location = PoSl::new(0, cr.EntryName.offset);
(cl, cr)
}
#[allow(clippy::collapsible_if)]
#[allow(unused_assignments)]
#[allow(unused_variables)]
fn classify_root_(
path : &str,
parse_flags : i32,
) -> (
Classification, // classification
PoSl, // root
PoSl, // path_root_stripped
) {
debug_assert!(!path.is_empty());
{
let _ = parse_flags;
}
let mut tilde_0 = false;
let mut ix = -1;
for c in path.chars() {
ix += 1;
if '~' == c && 0 == ix {
tilde_0 = true;
continue;
}
if char_is_path_name_separator_(c) {
if 0 == ix {
return (
Classification::SlashRooted,
PoSl::empty(),
PoSl::new(0, path.len()),
);
}
if 1 == ix {
return (
Classification::HomeRooted,
PoSl::new(0, 1),
PoSl::new(1, path.len() - 1),
);
}
}
break;
}
if 0 == ix && tilde_0 {
return (
Classification::HomeRooted,
PoSl::new(0, 1),
PoSl::new(1, path.len() - 1),
);
}
(
Classification::Relative,
PoSl::empty(),
PoSl::new(0, path.len()),
)
}
fn char_is_path_name_separator_(c : char) -> bool {
c == '/'
}
fn find_last_slash_(s : &str) -> Option<usize> {
s.rfind('/')
}
fn count_directory_parts_(
s : &str,
parse_flags : i32,
) -> (
usize, // number_of_parts
usize, // number_of_dots_parts
) {
{
let _ = parse_flags;
}
let mut number_of_parts = 0usize;
let mut number_of_dots_parts = 0usize;
let mut prev = 'X';
let mut num_dots = 0;
for c in s.chars() {
if char_is_path_name_separator_(c) {
match num_dots {
1 | 2 => number_of_dots_parts += 1,
_ => (),
}
if char_is_path_name_separator_(prev) {
} else {
number_of_parts += 1;
}
num_dots = 0;
} else {
if '.' == c {
num_dots += 1;
} else {
num_dots += 100;
}
}
prev = c;
}
(number_of_parts, number_of_dots_parts)
}
#[cfg(test)]
mod tests {
#![allow(non_snake_case)]
use super::char_is_path_name_separator_;
#[test]
fn TEST_char_is_drive_letter__1() {
}
#[test]
fn TEST_char_is_path_name_separator__1() {
assert!(char_is_path_name_separator_('/'));
assert!(!char_is_path_name_separator_('\\'));
assert!(!char_is_path_name_separator_('-'));
assert!(!char_is_path_name_separator_(';'));
assert!(!char_is_path_name_separator_(':'));
assert!(!char_is_path_name_separator_('a'));
}
#[test]
fn TEST_classify_root__1() {
}
#[test]
fn TEST_count_directory_parts__1() {
}
#[test]
fn TEST_find_last_slash__1() {
}
}
}
pub mod windows {
use super::common::ClassificationResult;
use fastparse::fastparse::types::PositionalSlice as PoSl;
pub mod classification_flags {
pub const IGNORE_SLASH_RUNS : i32 = 0x00000001;
pub const IGNORE_INVALID_CHARS : i32 = 0x00000002;
pub const RECOGNISE_TILDE_HOME : i32 = 0x00000004;
pub const IGNORE_INVALID_CHARS_IN_LONG_PATH : i32 = 0x00000002;
}
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Classification {
InvalidSlashRuns = -3,
InvalidChars = -2,
Invalid = -1,
Unknown,
Empty,
Relative,
SlashRooted,
DriveLetterRelative,
DriveLetterRooted,
UncIncomplete,
UncRooted,
HomeRooted,
}
#[allow(clippy::collapsible_if)]
pub fn path_classify(
path : &str,
parse_flags : i32,
) -> (
Classification, // classification
ClassificationResult, // classification_result
) {
if path.is_empty() {
return (
Classification::Empty,
ClassificationResult::empty(),
);
}
let mut cr = ClassificationResult::empty();
cr.Input = PoSl::new(0, path.len());
let (cl, root, path_root_stripped) = classify_root_(path, parse_flags);
cr.Root = PoSl::new(0, root.len());
let last_slash = find_last_slash_(path_root_stripped.substring_of(path));
match last_slash {
Some(index) => {
let dir_len = index + 1;
cr.Directory = PoSl::new(root.len(), dir_len);
let (num_parts, num_dir_parts) =
count_directory_parts_(cr.Directory.substring_of(path), parse_flags);
cr.NumDirectoryParts = num_parts;
cr.NumDotsDirectoryParts = num_dir_parts;
cr.EntryName = PoSl::new(root.len() + dir_len, path_root_stripped.len() - dir_len);
},
None => {
cr.Directory = PoSl::new(root.len(), 0);
cr.EntryName = PoSl::new(root.len(), path_root_stripped.len());
},
}
if cr.EntryName.is_empty() {
cr.Stem = cr.EntryName;
cr.Extension = cr.EntryName;
} else {
let last_entry_dot = cr.EntryName.substring_of(path).rfind('.');
match last_entry_dot {
Some(index) => {
let mut is_dots = false;
if !is_dots && 1 == cr.EntryName.len() {
is_dots = true;
}
if !is_dots {
if 2 == cr.EntryName.len() {
if ".." == cr.EntryName.substring_of(path) {
is_dots = true;
}
}
}
if is_dots {
cr.Stem = cr.EntryName;
cr.Extension = PoSl::new(cr.EntryName.len(), 0);
} else {
cr.Stem = PoSl::new(cr.EntryName.offset, index);
cr.Extension = PoSl::new(cr.EntryName.offset + index, cr.EntryName.len() - index);
}
},
None => {
cr.Stem = cr.EntryName;
cr.Extension = PoSl::new(cr.EntryName.offset + cr.EntryName.len(), 0);
},
}
}
cr.Location = PoSl::new(0, cr.EntryName.offset);
(cl, cr)
}
#[allow(clippy::collapsible_if)]
#[allow(unused_assignments)]
#[allow(unused_variables)]
fn classify_root_(
path : &str,
parse_flags : i32,
) -> (
Classification, // classification
PoSl, // root
PoSl, // path_root_stripped
) {
debug_assert!(!path.is_empty());
{
let _ = parse_flags;
}
let mut c0 : char = '\0';
let mut c1 : char = '\0';
let mut c2 : char;
let mut is_drive_2 = false;
let mut ix = -1;
for c in path.chars() {
ix += 1;
match ix {
0 => c0 = c,
1 => c1 = c,
2 => c2 = c,
_ => (),
}
if ix == 1 {
if char_is_drive_letter_(c0) && ':' == c1 {
is_drive_2 = true;
}
if '~' == c0 && char_is_path_name_separator_(c1) {
return (
Classification::HomeRooted,
PoSl::new(0, 1),
PoSl::new(1, path.len() - 1),
);
}
}
if ix == 2 {
if is_drive_2 {
let classification = if char_is_path_name_separator_(c) {
Classification::DriveLetterRooted
} else {
Classification::DriveLetterRelative
};
return (
classification,
PoSl::new(0, 2),
PoSl::new(2, path.len() - 2),
);
}
}
if char_is_path_name_separator_(c) {
if 0 == ix {
return (
Classification::SlashRooted,
PoSl::empty(),
PoSl::new(0, path.len()),
);
}
break;
}
}
if 0 == ix && '~' == c0 {
return (
Classification::HomeRooted,
PoSl::new(0, 1),
PoSl::new(1, path.len() - 1),
);
}
(
Classification::Relative,
PoSl::empty(),
PoSl::new(0, path.len()),
)
}
#[allow(clippy::match_like_matches_macro)]
fn char_is_path_name_separator_(c : char) -> bool {
match c {
'/' => true,
'\\' => true,
_ => false,
}
}
fn find_last_slash_(s : &str) -> Option<usize> {
let last_fslash = s.rfind('/');
match last_fslash {
Some(index1) => {
let last_rslash = s[index1 + 1..].rfind('\\');
match last_rslash {
Some(index2) => {
if index2 > index1 {
Some(index2)
} else {
Some(index1)
}
},
None => last_fslash,
}
},
None => s.rfind('\\'),
}
}
fn count_directory_parts_(
s : &str,
parse_flags : i32,
) -> (
usize, // number_of_parts
usize, // number_of_dots_parts
) {
{
let _ = parse_flags;
}
let mut number_of_parts = 0usize;
let mut number_of_dots_parts = 0usize;
let mut prev = 'X';
let mut num_dots = 0;
for c in s.chars() {
if char_is_path_name_separator_(c) {
match num_dots {
1 | 2 => number_of_dots_parts += 1,
_ => (),
}
if char_is_path_name_separator_(prev) {
} else {
number_of_parts += 1;
}
num_dots = 0;
} else {
if '.' == c {
num_dots += 1;
} else {
num_dots += 100;
}
}
prev = c;
}
(number_of_parts, number_of_dots_parts)
}
#[allow(clippy::match_like_matches_macro)]
fn char_is_drive_letter_(c : char) -> bool {
match c {
'A'..='Z' => true,
'a'..='z' => true,
_ => false,
}
}
#[cfg(test)]
mod tests {
#![allow(non_snake_case)]
use super::{
char_is_drive_letter_,
char_is_path_name_separator_,
};
#[test]
fn TEST_char_is_drive_letter__1() {
assert!(char_is_drive_letter_('A'));
assert!(char_is_drive_letter_('C'));
assert!(char_is_drive_letter_('Z'));
assert!(char_is_drive_letter_('a'));
assert!(char_is_drive_letter_('c'));
assert!(char_is_drive_letter_('z'));
assert!(!char_is_drive_letter_(':'));
assert!(!char_is_drive_letter_('.'));
assert!(!char_is_drive_letter_('/'));
}
#[test]
fn TEST_char_is_path_name_separator__1() {
assert!(char_is_path_name_separator_('/'));
assert!(char_is_path_name_separator_('\\'));
assert!(!char_is_path_name_separator_('-'));
assert!(!char_is_path_name_separator_(';'));
assert!(!char_is_path_name_separator_(':'));
assert!(!char_is_path_name_separator_('a'));
}
#[test]
fn TEST_classify_root__1() {
}
#[test]
fn TEST_count_directory_parts__1() {
}
#[test]
fn TEST_find_last_slash__1() {
}
}
}
}
#[cfg(test)]
mod tests {
#![allow(non_snake_case)]
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
use crate::libpath::util::{
common::ClassificationResult,
};
use fastparse::fastparse::types::PositionalSlice as PoSl;
#[allow(non_snake_case)]
mod unix {
use crate::libpath::util::unix::{
classification_flags::*,
path_classify,
Classification,
};
use super::*;
#[test]
fn TEST_path_classify_WITH_EMPTY_INPUT() {
let flag_max = IGNORE_SLASH_RUNS | IGNORE_INVALID_CHARS | RECOGNISE_TILDE_HOME;
for flags in 0..=flag_max {
let (cl, cr) = path_classify("", flags);
assert_eq!(Classification::Empty, cl);
assert_eq!(ClassificationResult::empty(), cr);
}
}
#[test]
fn TEST_path_classify_entry_only() {
{
let path = "name.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 8), cr.EntryName);
assert_eq!(PoSl::new(0, 4), cr.Stem);
assert_eq!(PoSl::new(4, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("name.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("name.ext", cr.EntryName.substring_of(path));
assert_eq!("name", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = "name";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 4), cr.EntryName);
assert_eq!(PoSl::new(0, 4), cr.Stem);
assert_eq!(PoSl::new(4, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("name", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("name", cr.EntryName.substring_of(path));
assert_eq!("name", cr.Stem.substring_of(path));
assert_eq!("", cr.Extension.substring_of(path));
}
{
let path = ".ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 4), cr.EntryName);
assert_eq!(PoSl::new(0, 0), cr.Stem);
assert_eq!(PoSl::new(0, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!(".ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!(".ext", cr.EntryName.substring_of(path));
assert_eq!("", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = "ab.";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("ab.", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("ab.", cr.EntryName.substring_of(path));
}
{
let path = "a..";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("a..", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("a..", cr.EntryName.substring_of(path));
}
{
let path = "...";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("...", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("...", cr.EntryName.substring_of(path));
}
}
#[test]
fn TEST_path_classify_rel_dir_and_name() {
let path = "dir/name.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 12), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 8), cr.EntryName);
assert_eq!(PoSl::new(4, 4), cr.Stem);
assert_eq!(PoSl::new(8, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("dir/name.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("dir/", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("dir/", cr.Directory.substring_of(path));
assert_eq!("name.ext", cr.EntryName.substring_of(path));
assert_eq!("name", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
#[test]
fn TEST_path_classify_WITH_RELATIVE_Directory_ONLY() {
{
let path = "dir/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 0), cr.EntryName);
assert_eq!(PoSl::new(4, 0), cr.Stem);
assert_eq!(PoSl::new(4, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("dir/", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("dir/", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("dir/", cr.Directory.substring_of(path));
assert_eq!("", cr.EntryName.substring_of(path));
assert_eq!("", cr.Stem.substring_of(path));
assert_eq!("", cr.Extension.substring_of(path));
}
{
let path = "dir1/dir2/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 10), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 10), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 10), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(10, 0), cr.EntryName);
assert_eq!(PoSl::new(10, 0), cr.Stem);
assert_eq!(PoSl::new(10, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "dir1/../";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 8), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 8), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(1, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(8, 0), cr.EntryName);
assert_eq!(PoSl::new(8, 0), cr.Stem);
assert_eq!(PoSl::new(8, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "../dir1/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 8), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 8), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(1, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(8, 0), cr.EntryName);
assert_eq!(PoSl::new(8, 0), cr.Stem);
assert_eq!(PoSl::new(8, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = ".././";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 5), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 5), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 5), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(2, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(5, 0), cr.EntryName);
assert_eq!(PoSl::new(5, 0), cr.Stem);
assert_eq!(PoSl::new(5, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "dir-1/../././././././././././abc";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 32), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 29), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 29), cr.Directory);
assert_eq!(12, cr.NumDirectoryParts);
assert_eq!(11, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(29, 3), cr.EntryName);
assert_eq!(PoSl::new(29, 3), cr.Stem);
assert_eq!(PoSl::new(32, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
}
#[test]
fn TEST_path_classify_WITH_DOTS1_ONLY_INTERPRETED_AS_Stem() {
let path = ".";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 1), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 1), cr.EntryName);
assert_eq!(PoSl::new(0, 1), cr.Stem);
assert_eq!(PoSl::new(1, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_WITH_DOTS2_ONLY_INTERPRETED_AS_Stem() {
let path = "..";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 2), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 2), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_WITH_DOTS3_ONLY_INTERPRETED_AS_Stem() {
let path = "...";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_WITH_SLASHROOTED_PATH() {
let path = "/dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::SlashRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 21), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 13), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(13, 8), cr.EntryName);
assert_eq!(PoSl::new(13, 4), cr.Stem);
assert_eq!(PoSl::new(17, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("/dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
#[test]
fn TEST_path_classify_WITH_HomeRooted_PATH_WITH__RECOGNISE_TILDE_HOME() {
let path = "~/dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::HomeRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 22), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 14), cr.Location);
assert_eq!(PoSl::new(0, 1), cr.Root);
assert_eq!(PoSl::new(1, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(14, 8), cr.EntryName);
assert_eq!(PoSl::new(14, 4), cr.Stem);
assert_eq!(PoSl::new(18, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("~/dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("~/dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("~", cr.Root.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
#[test]
fn TEST_path_classify_WITH_HOME_ONLY_WITHOUT__RECOGNISE_TILDE_HOME() {
let path = "~";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::HomeRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 1), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 1), cr.Location);
assert_eq!(PoSl::new(0, 1), cr.Root);
assert_eq!(PoSl::new(1, 0), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(1, 0), cr.EntryName);
assert_eq!(PoSl::new(1, 0), cr.Stem);
assert_eq!(PoSl::new(1, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("~", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("~", cr.Location.substring_of(path));
assert_eq!("~", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("", cr.EntryName.substring_of(path));
assert_eq!("", cr.Stem.substring_of(path));
assert_eq!("", cr.Extension.substring_of(path));
}
}
#[allow(non_snake_case)]
mod windows {
use crate::libpath::util::windows::{
classification_flags::*,
path_classify,
Classification,
};
use super::*;
#[test]
fn TEST_path_classify_WITH_EMPTY_INPUT() {
let flag_max =
IGNORE_SLASH_RUNS | IGNORE_INVALID_CHARS | RECOGNISE_TILDE_HOME | IGNORE_INVALID_CHARS_IN_LONG_PATH;
for flags in 0..=flag_max {
let (cl, cr) = path_classify("", flags);
assert_eq!(Classification::Empty, cl);
assert_eq!(ClassificationResult::empty(), cr);
}
}
#[test]
fn TEST_path_classify_entry_only() {
{
let path = "name.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 8), cr.EntryName);
assert_eq!(PoSl::new(0, 4), cr.Stem);
assert_eq!(PoSl::new(4, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("name.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("name.ext", cr.EntryName.substring_of(path));
assert_eq!("name", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = "name";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 4), cr.EntryName);
assert_eq!(PoSl::new(0, 4), cr.Stem);
assert_eq!(PoSl::new(4, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = ".ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 4), cr.EntryName);
assert_eq!(PoSl::new(0, 0), cr.Stem);
assert_eq!(PoSl::new(0, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "ab.";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "a..";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "...";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 3), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 1), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
}
#[test]
fn TEST_path_classify_rel_dir_and_name() {
{
let path = "dir/name.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 12), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 8), cr.EntryName);
assert_eq!(PoSl::new(4, 4), cr.Stem);
assert_eq!(PoSl::new(8, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = r"dir\name.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 12), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 8), cr.EntryName);
assert_eq!(PoSl::new(4, 4), cr.Stem);
assert_eq!(PoSl::new(8, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
}
#[test]
fn TEST_path_classify_WITH_RELATIVE_Directory_ONLY() {
{
let path = "dir/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 0), cr.EntryName);
assert_eq!(PoSl::new(4, 0), cr.Stem);
assert_eq!(PoSl::new(4, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("dir/", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("dir/", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("dir/", cr.Directory.substring_of(path));
assert_eq!("", cr.EntryName.substring_of(path));
assert_eq!("", cr.Stem.substring_of(path));
assert_eq!("", cr.Extension.substring_of(path));
}
{
let path = "dir1/dir2/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 10), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 10), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 10), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(10, 0), cr.EntryName);
assert_eq!(PoSl::new(10, 0), cr.Stem);
assert_eq!(PoSl::new(10, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "dir1/../";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 8), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 8), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(1, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(8, 0), cr.EntryName);
assert_eq!(PoSl::new(8, 0), cr.Stem);
assert_eq!(PoSl::new(8, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = "../dir1/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 8), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 8), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 8), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(1, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(8, 0), cr.EntryName);
assert_eq!(PoSl::new(8, 0), cr.Stem);
assert_eq!(PoSl::new(8, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = ".././";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 5), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 5), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 5), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(2, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(5, 0), cr.EntryName);
assert_eq!(PoSl::new(5, 0), cr.Stem);
assert_eq!(PoSl::new(5, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = r"dir\";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 4), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 4), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 4), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(4, 0), cr.EntryName);
assert_eq!(PoSl::new(4, 0), cr.Stem);
assert_eq!(PoSl::new(4, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
{
let path = r"dir1\dir2\";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 10), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 10), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 10), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(10, 0), cr.EntryName);
assert_eq!(PoSl::new(10, 0), cr.Stem);
assert_eq!(PoSl::new(10, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
}
#[test]
fn TEST_path_classify_WITH_DOTS1_ONLY_INTERPRETED_AS_Stem() {
let path = ".";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 1), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 1), cr.EntryName);
assert_eq!(PoSl::new(0, 1), cr.Stem);
assert_eq!(PoSl::new(1, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_WITH_DOTS2_ONLY_INTERPRETED_AS_Stem() {
let path = "..";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::Relative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 2), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::empty(), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::empty(), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(0, 2), cr.EntryName);
assert_eq!(PoSl::new(0, 2), cr.Stem);
assert_eq!(PoSl::new(2, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_root() {
let path = "C:/";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::DriveLetterRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 3), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 3), cr.Location);
assert_eq!(PoSl::new(0, 2), cr.Root);
assert_eq!(PoSl::new(2, 1), cr.Directory);
assert_eq!(1, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(3, 0), cr.EntryName);
assert_eq!(PoSl::new(3, 0), cr.Stem);
assert_eq!(PoSl::new(3, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
}
#[test]
fn TEST_path_classify_WITH_SLASHROOTED_PATH() {
{
let path = "/dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::SlashRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 21), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 13), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(13, 8), cr.EntryName);
assert_eq!(PoSl::new(13, 4), cr.Stem);
assert_eq!(PoSl::new(17, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("/dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = r"\dir\sub-dir\file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::SlashRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 21), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 13), cr.Location);
assert_eq!(PoSl::empty(), cr.Root);
assert_eq!(PoSl::new(0, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(13, 8), cr.EntryName);
assert_eq!(PoSl::new(13, 4), cr.Stem);
assert_eq!(PoSl::new(17, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!(r"\dir\sub-dir\file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!(r"\dir\sub-dir\", cr.Location.substring_of(path));
assert_eq!("", cr.Root.substring_of(path));
assert_eq!(r"\dir\sub-dir\", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
}
#[test]
fn TEST_path_classify_WITH_DriveLetterRooted_PATH() {
{
let path = "C:/dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::DriveLetterRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 23), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 15), cr.Location);
assert_eq!(PoSl::new(0, 2), cr.Root);
assert_eq!(PoSl::new(2, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(15, 8), cr.EntryName);
assert_eq!(PoSl::new(15, 4), cr.Stem);
assert_eq!(PoSl::new(19, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("C:/dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("C:/dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("C:", cr.Root.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = r"C:\dir\sub-dir\file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::DriveLetterRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 23), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 15), cr.Location);
assert_eq!(PoSl::new(0, 2), cr.Root);
assert_eq!(PoSl::new(2, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(15, 8), cr.EntryName);
assert_eq!(PoSl::new(15, 4), cr.Stem);
assert_eq!(PoSl::new(19, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!(r"C:\dir\sub-dir\file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!(r"C:\dir\sub-dir\", cr.Location.substring_of(path));
assert_eq!("C:", cr.Root.substring_of(path));
assert_eq!(r"\dir\sub-dir\", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
}
#[test]
fn TEST_path_classify_WITH_DriveLetterRelative_PATH() {
{
let path = "C:dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::DriveLetterRelative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 22), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 14), cr.Location);
assert_eq!(PoSl::new(0, 2), cr.Root);
assert_eq!(PoSl::new(2, 12), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(14, 8), cr.EntryName);
assert_eq!(PoSl::new(14, 4), cr.Stem);
assert_eq!(PoSl::new(18, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("C:dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("C:dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("C:", cr.Root.substring_of(path));
assert_eq!("dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
{
let path = r"C:dir\sub-dir\file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::DriveLetterRelative, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 22), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 14), cr.Location);
assert_eq!(PoSl::new(0, 2), cr.Root);
assert_eq!(PoSl::new(2, 12), cr.Directory);
assert_eq!(2, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(14, 8), cr.EntryName);
assert_eq!(PoSl::new(14, 4), cr.Stem);
assert_eq!(PoSl::new(18, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!(r"C:dir\sub-dir\file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!(r"C:dir\sub-dir\", cr.Location.substring_of(path));
assert_eq!("C:", cr.Root.substring_of(path));
assert_eq!(r"dir\sub-dir\", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
}
#[test]
fn TEST_path_classify_WITH_HomeRooted_PATH_WITH__RECOGNISE_TILDE_HOME() {
let path = "~/dir/sub-dir/file.ext";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::HomeRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 22), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 14), cr.Location);
assert_eq!(PoSl::new(0, 1), cr.Root);
assert_eq!(PoSl::new(1, 13), cr.Directory);
assert_eq!(3, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(14, 8), cr.EntryName);
assert_eq!(PoSl::new(14, 4), cr.Stem);
assert_eq!(PoSl::new(18, 4), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("~/dir/sub-dir/file.ext", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("~/dir/sub-dir/", cr.Location.substring_of(path));
assert_eq!("~", cr.Root.substring_of(path));
assert_eq!("/dir/sub-dir/", cr.Directory.substring_of(path));
assert_eq!("file.ext", cr.EntryName.substring_of(path));
assert_eq!("file", cr.Stem.substring_of(path));
assert_eq!(".ext", cr.Extension.substring_of(path));
}
#[test]
fn TEST_path_classify_WITH_HOME_ONLY_WITHOUT__RECOGNISE_TILDE_HOME() {
let path = "~";
let parse_flags : i32 = 0;
let (cl, cr) = path_classify(path, parse_flags);
assert_eq!(Classification::HomeRooted, cl);
assert_ne!(ClassificationResult::empty(), cr);
assert_eq!(PoSl::new(0, 1), cr.Input);
assert_eq!(PoSl::empty(), cr.Prefix);
assert_eq!(PoSl::new(0, 1), cr.Location);
assert_eq!(PoSl::new(0, 1), cr.Root);
assert_eq!(PoSl::new(1, 0), cr.Directory);
assert_eq!(0, cr.NumDirectoryParts);
assert_eq!(0, cr.NumDotsDirectoryParts);
assert_eq!(PoSl::new(1, 0), cr.EntryName);
assert_eq!(PoSl::new(1, 0), cr.Stem);
assert_eq!(PoSl::new(1, 0), cr.Extension);
assert!(cr.FirstInvalid.is_empty());
assert_eq!("~", cr.Input.substring_of(path));
assert_eq!("", cr.Prefix.substring_of(path));
assert_eq!("~", cr.Location.substring_of(path));
assert_eq!("~", cr.Root.substring_of(path));
assert_eq!("", cr.Directory.substring_of(path));
assert_eq!("", cr.EntryName.substring_of(path));
assert_eq!("", cr.Stem.substring_of(path));
assert_eq!("", cr.Extension.substring_of(path));
}
}
}