1 use std::fmt::Display;
2 use std::fmt::Error;
3 use std::fmt::Formatter;
4 use std::str::FromStr;
5 
6 use serde::ser::{Serialize, Serializer};
7 
8 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Hash)]
9 pub enum Field {
10     Name,
11     Path,
12     AbsPath,
13     Extension,
14     Directory,
15     AbsDir,
16     Size,
17     FormattedSize,
18     Uid,
19     Gid,
20     User,
21     Group,
22     Created,
23     Accessed,
24     Modified,
25     IsDir,
26     IsFile,
27     IsSymlink,
28     IsPipe,
29     IsCharacterDevice,
30     IsBlockDevice,
31     IsSocket,
32     Device,
33     Inode,
34     Blocks,
35     Hardlinks,
36     Mode,
37     UserRead,
38     UserWrite,
39     UserExec,
40     UserAll,
41     GroupRead,
42     GroupWrite,
43     GroupExec,
44     GroupAll,
45     OtherRead,
46     OtherWrite,
47     OtherExec,
48     OtherAll,
49     Suid,
50     Sgid,
51     IsHidden,
52     HasXattrs,
53     IsShebang,
54     IsEmpty,
55     Width,
56     Height,
57     Duration,
58     Bitrate,
59     Freq,
60     Title,
61     Artist,
62     Album,
63     Year,
64     Genre,
65     ExifDateTime,
66     ExifGpsAltitude,
67     ExifGpsLatitude,
68     ExifGpsLongitude,
69     ExifMake,
70     ExifModel,
71     ExifSoftware,
72     ExifVersion,
73     Mime,
74     LineCount,
75     IsBinary,
76     IsText,
77     IsArchive,
78     IsAudio,
79     IsBook,
80     IsDoc,
81     IsImage,
82     IsSource,
83     IsVideo,
84     Sha1,
85     Sha256,
86     Sha512,
87     Sha3,
88 }
89 
90 impl FromStr for Field {
91     type Err = String;
92 
93     fn from_str(s: &str) -> Result<Self, Self::Err> {
94         let field = s.to_ascii_lowercase();
95 
96         match field.as_str() {
97             "name" => Ok(Field::Name),
98             "ext" | "extension" => Ok(Field::Extension),
99             "path" => Ok(Field::Path),
100             "abspath" => Ok(Field::AbsPath),
101             "dir" | "directory" | "dirname" => Ok(Field::Directory),
102             "absdir" => Ok(Field::AbsDir),
103             "size" => Ok(Field::Size),
104             "fsize" | "hsize" => Ok(Field::FormattedSize),
105             "uid" => Ok(Field::Uid),
106             "gid" => Ok(Field::Gid),
107             "user" => Ok(Field::User),
108             "group" => Ok(Field::Group),
109             "created" => Ok(Field::Created),
110             "accessed" => Ok(Field::Accessed),
111             "modified" => Ok(Field::Modified),
112             "is_dir" => Ok(Field::IsDir),
113             "is_file" => Ok(Field::IsFile),
114             "is_symlink" => Ok(Field::IsSymlink),
115             "is_pipe" | "is_fifo" => Ok(Field::IsPipe),
116             "is_char" | "is_character" => Ok(Field::IsCharacterDevice),
117             "is_block" => Ok(Field::IsBlockDevice),
118             "is_socket" => Ok(Field::IsSocket),
119             "device" => Ok(Field::Device),
120             "inode" => Ok(Field::Inode),
121             "blocks" => Ok(Field::Blocks),
122             "hardlinks" => Ok(Field::Hardlinks),
123             "mode" => Ok(Field::Mode),
124             "user_read" => Ok(Field::UserRead),
125             "user_write" => Ok(Field::UserWrite),
126             "user_exec" => Ok(Field::UserExec),
127             "user_all" | "user_rwx" => Ok(Field::UserAll),
128             "group_read" => Ok(Field::GroupRead),
129             "group_write" => Ok(Field::GroupWrite),
130             "group_exec" => Ok(Field::GroupExec),
131             "group_all" | "group_rwx" => Ok(Field::GroupAll),
132             "other_read" => Ok(Field::OtherRead),
133             "other_write" => Ok(Field::OtherWrite),
134             "other_exec" => Ok(Field::OtherExec),
135             "other_all" | "other_rwx" => Ok(Field::OtherAll),
136             "suid" => Ok(Field::Suid),
137             "sgid" => Ok(Field::Sgid),
138             "is_hidden" => Ok(Field::IsHidden),
139             "has_xattrs" => Ok(Field::HasXattrs),
140             "is_shebang" => Ok(Field::IsShebang),
141             "is_empty" => Ok(Field::IsEmpty),
142             "width" => Ok(Field::Width),
143             "height" => Ok(Field::Height),
144             "mime" => Ok(Field::Mime),
145             "line_count" => Ok(Field::LineCount),
146             "duration" => Ok(Field::Duration),
147             "mp3_bitrate" | "bitrate" => Ok(Field::Bitrate),
148             "mp3_freq" | "freq" => Ok(Field::Freq),
149             "mp3_title" | "title" => Ok(Field::Title),
150             "mp3_artist" | "artist" => Ok(Field::Artist),
151             "mp3_album" | "album" => Ok(Field::Album),
152             "mp3_year" => Ok(Field::Year),
153             "mp3_genre" | "genre" => Ok(Field::Genre),
154             "exif_altitude" | "exif_alt" => Ok(Field::ExifGpsAltitude),
155             "exif_datetime" => Ok(Field::ExifDateTime),
156             "exif_latitude" | "exif_lat" => Ok(Field::ExifGpsLatitude),
157             "exif_longitude" | "exif_lon" | "exif_lng" => Ok(Field::ExifGpsLongitude),
158             "exif_make" => Ok(Field::ExifMake),
159             "exif_model" => Ok(Field::ExifModel),
160             "exif_software" => Ok(Field::ExifSoftware),
161             "exif_version" => Ok(Field::ExifVersion),
162             "is_binary" => Ok(Field::IsBinary),
163             "is_text" => Ok(Field::IsText),
164             "is_archive" => Ok(Field::IsArchive),
165             "is_audio" => Ok(Field::IsAudio),
166             "is_book" => Ok(Field::IsBook),
167             "is_doc" => Ok(Field::IsDoc),
168             "is_image" => Ok(Field::IsImage),
169             "is_source" => Ok(Field::IsSource),
170             "is_video" => Ok(Field::IsVideo),
171             "sha1" => Ok(Field::Sha1),
172             "sha2_256" | "sha256" => Ok(Field::Sha256),
173             "sha2_512" | "sha512" => Ok(Field::Sha512),
174             "sha3_512" | "sha3" => Ok(Field::Sha3),
175             _ => {
176                 let err = String::from("Unknown field ") + &field;
177                 Err(err)
178             }
179         }
180     }
181 }
182 
183 impl Display for Field {
184     fn fmt(&self, f: &mut Formatter) -> Result<(), Error>{
185         write!(f, "{:?}", self)
186     }
187 }
188 
189 impl Serialize for Field {
190     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
191         where S: Serializer
192     {
193         serializer.serialize_str(&self.to_string())
194     }
195 }
196 
197 impl Field {
198     pub fn is_numeric_field(&self) -> bool {
199         match self {
200             Field::Size | Field::FormattedSize
201             | Field::Uid | Field::Gid
202             | Field::Width | Field::Height
203             | Field::LineCount
204             | Field::Duration
205             | Field::Bitrate | Field::Freq | Field::Year => true,
206             _ => false
207         }
208     }
209 
210     pub fn is_datetime_field(&self) -> bool {
211         match self {
212             Field::Created | Field::Accessed | Field::Modified
213             | Field::ExifDateTime => true,
214             _ => false
215         }
216     }
217 
218     pub fn is_available_for_archived_files(&self) -> bool {
219         match self {
220             Field::Name
221             | Field::Extension
222             | Field::Path
223             | Field::AbsPath
224             | Field::Directory
225             | Field::AbsDir
226             | Field::Size
227             | Field::FormattedSize
228             | Field::IsDir
229             | Field::IsFile
230             | Field::IsSymlink
231             | Field::IsPipe
232             | Field::IsCharacterDevice
233             | Field::IsBlockDevice
234             | Field::IsSocket
235             | Field::Mode
236             | Field::UserRead
237             | Field::UserWrite
238             | Field::UserExec
239             | Field::UserAll
240             | Field::GroupRead
241             | Field::GroupWrite
242             | Field::GroupExec
243             | Field::GroupAll
244             | Field::OtherRead
245             | Field::OtherWrite
246             | Field::OtherExec
247             | Field::OtherAll
248             | Field::Suid
249             | Field::Sgid
250             | Field::IsHidden
251             | Field::IsEmpty
252             | Field::Modified
253             | Field::IsArchive
254             | Field::IsAudio
255             | Field::IsBook
256             | Field::IsDoc
257             | Field::IsImage
258             | Field::IsSource
259             | Field::IsVideo
260             => true,
261             _ => false
262         }
263     }
264 
265     pub fn is_colorized_field(&self) -> bool {
266         match self {
267             Field::Name => true,
268             _ => false
269         }
270     }
271 }