Skip to main content

fancy_tree/tree/entry/attributes/
file.rs

1//! Module for file attributes.
2use super::interop::{has_hidden_attribute, is_executable};
3use gengo_language::Language;
4use std::fs::{File, Metadata};
5use std::io::{self, Read};
6use std::path::Path;
7
8/// The maximum number of bytes to read from a file to determine its language.
9const READ_LIMIT: u16 = 1024 * 16; // 16 KiB
10
11/// Attributes for a file.
12pub struct FileAttributes {
13    /// Does the file have the hidden attribute set?
14    ///
15    /// Always `false` on Unix.
16    hidden: bool,
17    /// The file's language.
18    language: Option<Language>,
19    /// Is the file an executable?
20    executable: bool,
21}
22
23impl FileAttributes {
24    /// Creates file attributes.
25    pub(super) fn new<P>(path: P, file: File, metadata: Metadata) -> io::Result<Self>
26    where
27        P: AsRef<Path>,
28    {
29        let mut contents = file.take(READ_LIMIT.into());
30        let mut buf = vec![0; READ_LIMIT.into()];
31        let n = contents.read(&mut buf)?;
32        buf.truncate(n);
33        let language = Language::pick(&path, &buf, READ_LIMIT.into());
34
35        let attributes = FileAttributes {
36            hidden: has_hidden_attribute(&metadata),
37            language,
38            executable: is_executable(path, &metadata),
39        };
40        Ok(attributes)
41    }
42
43    /// Is the file hidden?
44    #[inline]
45    pub const fn is_hidden(&self) -> bool {
46        self.hidden
47    }
48
49    /// Is the file an executable?
50    #[inline]
51    pub const fn is_executable(&self) -> bool {
52        self.executable
53    }
54
55    /// Get the file's language.
56    #[inline]
57    pub const fn language(&self) -> Option<Language> {
58        self.language
59    }
60}