use std::cmp::Ordering;
use crate::config::{Config, DirKind, OrderKind};
use crate::finder::File;
pub struct Sorter<'a> {
config: &'a Config,
}
impl<'a> Sorter<'a> {
pub fn new(config: &Config) -> Sorter {
Sorter { config }
}
pub fn sort_files(&self, files: &mut Vec<File>) {
files.sort_unstable_by(|x, y| self.cmp_files(x, y));
}
fn cmp_files(&self, left: &File, right: &File) -> Ordering {
for order in &self.config.order_files {
let result = match order {
OrderKind::Dir => Self::cmp_dirs(left, right),
OrderKind::Group => Self::cmp_groups(left, right),
OrderKind::Name => Self::cmp_names(left, right),
OrderKind::Ext => Self::cmp_exts(left, right),
OrderKind::Size(dir) => Self::cmp_sizes(left, right, dir),
OrderKind::Time(dir) => Self::cmp_times(left, right, dir),
};
if result != Ordering::Equal {
return result;
}
}
return Ordering::Equal;
}
fn cmp_dirs(left: &File, right: &File) -> Ordering {
if let Some(left) = left.abs_dir.to_str() {
if let Some(right) = right.abs_dir.to_str() {
let result = Self::cmp_strings(left, right);
if result != Ordering::Equal {
return result;
}
}
}
return Self::cmp_groups(left, right);
}
fn cmp_groups(left: &File, right: &File) -> Ordering {
let left = left.group_dir_before_file();
let right = right.group_dir_before_file();
return left.cmp(&right);
}
fn cmp_names(left: &File, right: &File) -> Ordering {
Self::cmp_strings(&left.file_name, &right.file_name)
}
fn cmp_exts(left: &File, right: &File) -> Ordering {
Self::cmp_strings(&left.file_ext, &right.file_ext)
}
fn cmp_strings(left: &str, right: &str) -> Ordering {
let result = natord::compare_ignore_case(left, right);
if result != Ordering::Equal {
return result;
}
let result = natord::compare(left, right);
if result != Ordering::Equal {
return result;
}
return Ordering::Equal;
}
fn cmp_sizes(left: &File, right: &File, dir: &DirKind) -> Ordering {
let result = left.file_size.cmp(&right.file_size);
match dir {
DirKind::Asc => result,
DirKind::Desc => result.reverse(),
}
}
fn cmp_times(left: &File, right: &File, dir: &DirKind) -> Ordering {
let result = left.file_time.cmp(&right.file_time);
match dir {
DirKind::Asc => result,
DirKind::Desc => result.reverse(),
}
}
}
#[cfg(test)]
mod tests {
use std::ffi::OsStr;
use std::path::{MAIN_SEPARATOR_STR, PathBuf};
use chrono::{DateTime, Utc};
use pretty_assertions::assert_eq;
use crate::config::EntryKind;
use super::*;
#[test]
fn test_files_are_sorted_by_path() {
let expected = string_from(vec![
"index",
"cheese/",
"cheese/index",
"cheese/english/",
"cheese/english/cheddar.xy",
"cheese/english/stilton.ij",
"cheese/french/",
"cheese/french/bleu.xy",
"cheese/french/brie.ij",
"fruit/",
"fruit/apple.xy",
"fruit/banana.ij",
"fruit/cherry.xy",
"fruit/date.ij",
"fruit/orange.xy",
"fruit/pear.ij",
]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_dir_and_size() {
let expected = string_from(vec![
"index", "cheese/", "cheese/index", "cheese/english/", "cheese/english/stilton.ij", "cheese/english/cheddar.xy", "cheese/french/", "cheese/french/brie.ij", "cheese/french/bleu.xy", "fruit/", "fruit/date.ij", "fruit/banana.ij", "fruit/orange.xy", "fruit/pear.ij", "fruit/apple.xy", "fruit/cherry.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Size(DirKind::Asc), OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_dir_and_time() {
let expected = string_from(vec![
"index", "cheese/", "cheese/index", "cheese/english/", "cheese/english/cheddar.xy", "cheese/english/stilton.ij", "cheese/french/", "cheese/french/bleu.xy", "cheese/french/brie.ij", "fruit/", "fruit/date.ij", "fruit/cherry.xy", "fruit/pear.ij", "fruit/apple.xy", "fruit/banana.ij", "fruit/orange.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Time(DirKind::Asc), OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_name() {
let expected = string_from(vec![
"cheese/", "cheese/english/", "cheese/french/", "fruit/", "fruit/apple.xy", "fruit/banana.ij", "cheese/french/bleu.xy", "cheese/french/brie.ij", "cheese/english/cheddar.xy", "fruit/cherry.xy", "fruit/date.ij", "index", "cheese/index", "fruit/orange.xy", "fruit/pear.ij", "cheese/english/stilton.ij", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Name, OrderKind::Dir]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_ext() {
let expected = string_from(vec![
"index", "cheese/", "cheese/index", "cheese/english/", "cheese/french/", "fruit/", "cheese/english/stilton.ij", "cheese/french/brie.ij", "fruit/banana.ij", "fruit/date.ij", "fruit/pear.ij", "cheese/english/cheddar.xy", "cheese/french/bleu.xy", "fruit/apple.xy", "fruit/cherry.xy", "fruit/orange.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Ext, OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_ext_and_size() {
let expected = string_from(vec![
"cheese/", "cheese/english/", "cheese/french/", "fruit/", "index", "cheese/index", "fruit/date.ij", "fruit/banana.ij", "cheese/english/stilton.ij", "fruit/pear.ij", "cheese/french/brie.ij", "fruit/orange.xy", "fruit/apple.xy", "fruit/cherry.xy", "cheese/english/cheddar.xy", "cheese/french/bleu.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Ext, OrderKind::Size(DirKind::Asc), OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_size_asc() {
let expected = string_from(vec![
"cheese/", "cheese/english/", "cheese/french/", "fruit/", "fruit/date.ij", "index", "fruit/banana.ij", "cheese/english/stilton.ij", "cheese/index", "fruit/orange.xy", "fruit/pear.ij", "fruit/apple.xy", "fruit/cherry.xy", "cheese/english/cheddar.xy", "cheese/french/brie.ij", "cheese/french/bleu.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Size(DirKind::Asc), OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_size_desc() {
let expected = string_from(vec![
"cheese/french/bleu.xy", "cheese/french/brie.ij", "cheese/english/cheddar.xy", "fruit/cherry.xy", "fruit/apple.xy", "fruit/pear.ij", "fruit/orange.xy", "cheese/index", "cheese/english/stilton.ij", "fruit/banana.ij", "index", "fruit/date.ij", "cheese/", "cheese/english/", "cheese/french/", "fruit/", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Size(DirKind::Desc), OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_time_asc() {
let expected = string_from(vec![
"cheese/english/cheddar.xy", "cheese/french/", "cheese/french/bleu.xy", "fruit/date.ij", "fruit/cherry.xy", "cheese/index", "cheese/", "cheese/french/brie.ij", "fruit/pear.ij", "cheese/english/stilton.ij", "fruit/apple.xy", "fruit/banana.ij", "fruit/orange.xy", "index", "cheese/english/", "fruit/", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Time(DirKind::Asc), OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_time_desc() {
let expected = string_from(vec![
"fruit/", "cheese/english/", "index", "fruit/orange.xy", "fruit/banana.ij", "fruit/apple.xy", "cheese/english/stilton.ij", "fruit/pear.ij", "cheese/french/brie.ij", "cheese/", "cheese/index", "fruit/cherry.xy", "fruit/date.ij", "cheese/french/bleu.xy", "cheese/french/", "cheese/english/cheddar.xy", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Time(DirKind::Desc), OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_group() {
let expected = string_from(vec![
"cheese/", "cheese/english/", "cheese/french/", "fruit/", "index", "cheese/index", "cheese/english/cheddar.xy", "cheese/english/stilton.ij", "cheese/french/bleu.xy", "cheese/french/brie.ij", "fruit/apple.xy", "fruit/banana.ij", "fruit/cherry.xy", "fruit/date.ij", "fruit/orange.xy", "fruit/pear.ij", ]);
let files = create_files();
let paths = sort_files(files, vec![OrderKind::Group, OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_case_insensitive_path() {
let expected = string_from(vec![
"AAA.DD",
"AAA.dd",
"aaa.DD",
"aaa.dd",
"AAA.EE",
"AAA.ee",
"aaa.EE",
"aaa.ee",
"AAA.FF",
"AAA.ff",
"aaa.FF",
"aaa.ff",
"BBB.DD",
"BBB.dd",
"bbb.DD",
"bbb.dd",
"BBB.EE",
"BBB.ee",
"bbb.EE",
"bbb.ee",
"BBB.FF",
"BBB.ff",
"bbb.FF",
"bbb.ff",
"CCC.DD",
"CCC.dd",
"ccc.DD",
"ccc.dd",
"CCC.EE",
"CCC.ee",
"ccc.EE",
"ccc.ee",
"CCC.FF",
"CCC.ff",
"ccc.FF",
"ccc.ff",
]);
let files = create_case();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_by_case_insensitive_ext() {
let expected = string_from(vec![
"AAA.DD",
"aaa.DD",
"BBB.DD",
"bbb.DD",
"CCC.DD",
"ccc.DD",
"AAA.dd",
"aaa.dd",
"BBB.dd",
"bbb.dd",
"CCC.dd",
"ccc.dd",
"AAA.EE",
"aaa.EE",
"BBB.EE",
"bbb.EE",
"CCC.EE",
"ccc.EE",
"AAA.ee",
"aaa.ee",
"BBB.ee",
"bbb.ee",
"CCC.ee",
"ccc.ee",
"AAA.FF",
"aaa.FF",
"BBB.FF",
"bbb.FF",
"CCC.FF",
"ccc.FF",
"AAA.ff",
"aaa.ff",
"BBB.ff",
"bbb.ff",
"CCC.ff",
"ccc.ff",
]);
let files = create_case();
let paths = sort_files(files, vec![OrderKind::Ext, OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_files_are_sorted_before_dirs() {
let expected = string_from(vec![
"xyz",
"abc/",
"abc/xyz",
"abc/def/",
"abc/def/xyz",
]);
let files = create_folder();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_numeric_dirs_are_sorted_by_path() {
let expected = string_from(vec![
"9/",
"9/9/",
"9/9/9/",
"9/9/10/",
"9/10/",
"9/10/9/",
"9/10/10/",
"10/",
"10/9/",
"10/9/9/",
"10/9/10/",
"10/10/",
"10/10/9/",
"10/10/10/",
]);
let files = create_numeric1();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_numeric_files_are_sorted_by_path() {
let expected = string_from(vec![
"9",
"9_9",
"9_9_9",
"9_9_10",
"9_10",
"9_10_9",
"9_10_10",
"10",
"10_9",
"10_9_9",
"10_9_10",
"10_10",
"10_10_9",
"10_10_10",
]);
let files = create_numeric2();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_numeric_files_are_sorted_by_name() {
let expected = string_from(vec![
"9",
"9_9",
"9_9_9",
"9_9_10",
"9_10",
"9_10_9",
"9_10_10",
"10",
"10_9",
"10_9_9",
"10_9_10",
"10_10",
"10_10_9",
"10_10_10",
]);
let files = create_numeric2();
let paths = sort_files(files, vec![OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
#[test]
fn test_numeric_files_are_sorted_by_ext() {
let expected = string_from(vec![
"file.9",
"file.9_9",
"file.9_9_9",
"file.9_9_10",
"file.9_10",
"file.9_10_9",
"file.9_10_10",
"file.10",
"file.10_9",
"file.10_9_9",
"file.10_9_10",
"file.10_10",
"file.10_10_9",
"file.10_10_10",
]);
let files = create_numeric3();
let paths = sort_files(files, vec![OrderKind::Ext, OrderKind::Dir, OrderKind::Name]);
assert_eq!(expected, paths);
}
fn create_files() -> Vec<File> {
vec![
create_file(EntryKind::File, "2023-07-05T13:05:42Z", 42, "index"),
create_file(EntryKind::Dir, "2023-01-16T11:25:51Z", 0, "cheese"),
create_file(EntryKind::File, "2022-12-23T21:43:18Z", 99, "cheese/index"),
create_file(EntryKind::Dir, "2023-08-04T10:57:26Z", 0, "cheese/english"),
create_file(EntryKind::File, "2022-09-10T04:03:38Z", 6363, "cheese/english/cheddar.xy"),
create_file(EntryKind::File, "2023-04-07T03:08:29Z", 91, "cheese/english/stilton.ij"),
create_file(EntryKind::Dir, "2022-10-06T23:36:27Z", 0, "cheese/french"),
create_file(EntryKind::File, "2022-10-28T05:49:07Z", 20122, "cheese/french/bleu.xy"),
create_file(EntryKind::File, "2023-02-28T11:01:59Z", 8681, "cheese/french/brie.ij"),
create_file(EntryKind::Dir, "2023-08-14T01:53:00Z", 0, "fruit"),
create_file(EntryKind::File, "2023-05-10T11:24:22Z", 467, "fruit/apple.xy"),
create_file(EntryKind::File, "2023-06-10T02:06:38Z", 73, "fruit/banana.ij"),
create_file(EntryKind::File, "2022-12-19T02:12:38Z", 795, "fruit/cherry.xy"),
create_file(EntryKind::File, "2022-11-25T14:42:53Z", 6, "fruit/date.ij"),
create_file(EntryKind::File, "2023-06-29T21:16:08Z", 108, "fruit/orange.xy"),
create_file(EntryKind::File, "2023-03-27T05:45:33Z", 173, "fruit/pear.ij"),
]
}
fn create_case() -> Vec<File> {
vec![
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "aaa.FF"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "AAA.FF"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "bbb.FF"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "BBB.FF"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "ccc.FF"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.dd"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.DD"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.ee"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.EE"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.ff"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "CCC.FF"),
]
}
fn create_folder() -> Vec<File> {
vec![
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "abc"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "abc/def"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "abc/def/xyz"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "abc/xyz"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "xyz"),
]
}
fn create_numeric1() -> Vec<File> {
vec![
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/10/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/10/9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/9/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "10/9/9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/10/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/10/9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/9"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/9/10"),
create_file(EntryKind::Dir, "1970-01-01T00:00:00Z", 0, "9/9/9"),
]
}
fn create_numeric2() -> Vec<File> {
vec![
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "10_9_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "9_9_9"),
]
}
fn create_numeric3() -> Vec<File> {
vec![
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.10_9_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_10_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_10_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_9"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_9_10"),
create_file(EntryKind::File, "1970-01-01T00:00:00Z", 0, "file.9_9_9"),
]
}
fn create_file(
file_type: EntryKind,
file_time: &str,
file_size: u64,
rel_path: &str,
) -> File {
let abs_path = PathBuf::from("/root/").join(rel_path);
let rel_path = PathBuf::from(rel_path);
let file_depth = rel_path.components().count();
let file_time = DateTime::parse_from_rfc3339(file_time).unwrap().with_timezone(&Utc);
return if file_type == EntryKind::Dir {
let file_name = String::from("");
let file_ext = String::from("");
File {
abs_dir: abs_path,
rel_dir: rel_path,
link_path: None,
file_depth,
file_name,
file_ext,
file_type,
file_mode: 0,
file_size,
file_time,
}
} else {
let abs_dir = PathBuf::from(abs_path.parent().unwrap());
let rel_dir = PathBuf::from(rel_path.parent().unwrap());
let file_name = String::from(abs_path.file_name().and_then(OsStr::to_str).unwrap());
let file_ext = String::from(abs_path.extension().and_then(OsStr::to_str).unwrap_or(""));
File {
abs_dir,
rel_dir,
link_path: None,
file_depth,
file_name,
file_ext,
file_type,
file_mode: 0,
file_size,
file_time,
}
}
}
fn sort_files(mut files: Vec<File>, order: Vec<OrderKind>) -> Vec<String> {
let config = create_config(order);
let sorter = Sorter::new(&config);
sorter.sort_files(&mut files);
return files.into_iter().map(format_file).collect();
}
fn format_file(file: File) -> String {
file.rel_dir
.join(file.file_name)
.to_str()
.map(|x| String::from(x))
.map(|x| x.replace(MAIN_SEPARATOR_STR, "/"))
.unwrap()
}
fn create_config(order: Vec<OrderKind>) -> Config {
let mut config = Config::default();
config.order_files = order;
return config;
}
fn string_from(values: Vec<&str>) -> Vec<String> {
values.into_iter().map(String::from).collect()
}
}