oxedyne/fe2o3/fe2o3_file/src/tree.rs
2.5 KiB, 5 runs
created by r1870400018:304, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | use oxedyne_fe2o3_core::{ |
| 2 | prelude::*, |
| 3 | }; |
| 4 | use oxedyne_fe2o3_data::tree::{ |
| 5 | Branch, |
| 6 | Leaf, |
| 7 | Node, |
| 8 | NodeData, |
| 9 | Tree, |
| 10 | }; |
| 11 | |
| 12 | use std::{ |
| 13 | fs, |
| 14 | path::{ |
| 15 | Path, |
| 16 | PathBuf, |
| 17 | }, |
| 18 | time::SystemTime, |
| 19 | }; |
| 20 | |
| 21 | |
| 22 | #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] |
| 23 | pub struct Attributes { |
| 24 | path: PathBuf, |
| 25 | mod_time: SystemTime, |
| 26 | size: u64, |
| 27 | } |
| 28 | |
| 29 | impl NodeData for Attributes {} |
| 30 | |
| 31 | new_type!(FileTree, Tree<PathBuf, Attributes>, Clone, Debug); |
| 32 | |
| 33 | impl FileTree { |
| 34 | |
| 35 | pub fn new<P: AsRef<Path>>(path: P) -> Outcome<Self> { |
| 36 | let root = path.as_ref().to_path_buf(); |
| 37 | let nodes = res!(Self::read_nodes(&root)); |
| 38 | // Max theoretical directory depth estimates resulting from path length limits: |
| 39 | // Linux: 2047, |
| 40 | // Windows: 129 (default), |
| 41 | // MacOS: 507 |
| 42 | let mut tree = Tree::new( |
| 43 | root, |
| 44 | nodes, |
| 45 | 2048, |
| 46 | ); |
| 47 | tree.sort_by_name(); |
| 48 | res!(tree.set_node_focus(true)); |
| 49 | Ok(Self(tree)) |
| 50 | } |
| 51 | |
| 52 | pub fn read_nodes( |
| 53 | path: &Path, |
| 54 | ) |
| 55 | -> Outcome<Vec<Node<Attributes>>> |
| 56 | { |
| 57 | let mut nodes = Vec::new(); |
| 58 | |
| 59 | for entry_result in res!(fs::read_dir(path), IO, File) { |
| 60 | let entry = res!(entry_result, IO, File); |
| 61 | let node_type = res!(entry.file_type(), IO, File); |
| 62 | let node_path = entry.path(); |
| 63 | let metadata = res!(entry.metadata(), IO, File); |
| 64 | let size = metadata.len(); |
| 65 | let mod_time = metadata.modified().unwrap_or(SystemTime::UNIX_EPOCH); |
| 66 | |
| 67 | let node_name = match entry.file_name().to_str() { |
| 68 | Some(name) => name.to_string(), |
| 69 | None => String::from(""), |
| 70 | }; |
| 71 | |
| 72 | let data = Attributes { |
| 73 | path: node_path.clone(), |
| 74 | size, |
| 75 | mod_time, |
| 76 | }; |
| 77 | if node_type.is_file() { |
| 78 | nodes.push(Node::Leaf(Leaf { |
| 79 | name: node_name, |
| 80 | data, |
| 81 | focus: false, |
| 82 | selected: false, |
| 83 | })); |
| 84 | } else if node_type.is_dir() { |
| 85 | let subdir_nodes = res!(Self::read_nodes(&node_path)); |
| 86 | nodes.push(Node::Branch(Branch { |
| 87 | name: node_name, |
| 88 | data, |
| 89 | nodes: subdir_nodes, |
| 90 | expanded: false, |
| 91 | focus: false, |
| 92 | selected: false, |
| 93 | })); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | Ok(nodes) |
| 98 | } |
| 99 | } |