1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};

use chrono::{DateTime, Utc};

use crate::config::FileKind;

pub struct File {
    pub abs_dir: PathBuf,
    pub rel_dir: PathBuf,
    pub file_depth: usize,
    pub file_name: String,
    pub file_ext: String,
    pub file_type: FileKind,
    pub file_mode: u32,
    pub file_size: u64,
    pub file_time: Option<DateTime<Utc>>,
    pub link_data: Option<(PathBuf, FileKind)>,
}

impl File {
    pub fn new(
        abs_dir: PathBuf,
        rel_dir: PathBuf,
        file_depth: usize,
        file_name: String,
        file_ext: String,
        file_type: FileKind,
        file_mode: u32,
        file_size: u64,
        file_time: Option<DateTime<Utc>>,
        link_data: Option<(PathBuf, FileKind)>,
    ) -> Self {
        Self {
            abs_dir,
            rel_dir,
            file_depth,
            file_name,
            file_ext,
            file_type,
            file_mode,
            file_size,
            file_time,
            link_data,
        }
    }

    pub fn get_path(&self) -> PathBuf {
        self.abs_dir.join(&self.file_name)
    }

    pub fn select_dir(&self, abs_path: bool) -> &Path {
        if abs_path {
            &self.abs_dir
        } else {
            &self.rel_dir
        }
    }

    pub fn select_parent_for_indent(&self) -> Option<&Path> {
        if self.file_type == FileKind::Dir {
            self.rel_dir.parent()
        } else {
            Some(&self.rel_dir)
        }
    }

    pub fn select_name_for_indent(&self) -> Option<&str> {
        if self.file_type == FileKind::Dir {
            self.rel_dir.file_name().and_then(OsStr::to_str)
        } else {
            Some(&self.file_name)
        }
    }

    pub fn group_dir_before_file(&self) -> u8 {
        if self.file_type == FileKind::Dir { 0 } else { 1 }
    }
}

impl PartialEq for File {
    fn eq(&self, other: &Self) -> bool {
        (self.abs_dir == other.abs_dir) && (self.file_name == other.file_name)
    }
}

impl Eq for File {
}

impl Hash for File {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.abs_dir.hash(state);
        self.file_name.hash(state);
    }
}