extern crate notify; use notify::{ RecursiveMode, Watcher, Result, Event, }; use std:: { fs, path::Path, path::PathBuf, sync::mpsc, }; use crate:: { ROOT_DIR, }; #[derive(Copy,Clone)] enum Mode { Default, String, Name, Import, } pub fn watch_files(file_list: &[PathBuf]) -> u8 { let (tx, rx) = mpsc::channel::>(); // Use recommended_watcher() to automatically select the best implementation // for your platform. The `EventHandler` passed to this constructor can be a // closure, a `std::sync::mpsc::Sender`, a `crossbeam_channel::Sender`, or // another type the trait is implemented for. let mut watcher = notify::recommended_watcher(tx).expect("Watcher start failed"); // Add a path to be watched. All files and directories at that path and // below will be monitored for changes. watcher.watch(Path::new("root"), RecursiveMode::Recursive).expect("Path watching failed"); // Block forever, printing out events as they come in for res in rx { match res { Ok(event) => { // Ignore access event kinds as they're irrelevant if ! notify::EventKind::is_access(&event.kind) && file_list.contains(&event.paths[0]) { return 0 } }, Err(error) => { println!("watch error: {error:?}"); return 1 } } } println!("Watching files..."); 2 } pub fn read_file(file_name: &str, depth: u8) -> ( Vec, Vec, ) { if let Ok(file_contents) = fs::read_to_string(format!("root/{file_name}")) { let (bytes, file_list) = encode_npon(file_contents.as_str(), depth); return (bytes, file_list) } (vec![], vec![]) // return } /// Push a newline or tab character when there's a \n or \t /// Otherwise, just push the raw sequence fn backslash(bytes: &mut Vec, character: u8) { match character { 110 => // newline { bytes.push(14); }, 116 => // tab { bytes.push(15); }, _ => bytes.push(character), // Otherwise just push the character } } fn default_flag(bytes: &mut Vec, temp_string: &mut Vec, flag: &mut Mode, index_flag: &mut usize, character: u8, index: usize) { match character { 40 => { temp_string.push(3); // ( for name start *flag = Mode::Name; } 123 => bytes.push(5), 125 => bytes.push(6), 58 => { *index_flag = index + 1; *flag = Mode::Import; }, 39 | 34 => { temp_string.push(7); *flag = Mode::String; }, _ => (), } } fn encode_npon(file_contents: &str, depth: u8) -> ( Vec, Vec, ) { let mut bytes: Vec = vec![]; let mut file_list: Vec = vec![]; if depth > 63 { println!("Depth level safety reached (63), recursion error suspected"); return (vec![], file_list); } if depth == 0 { bytes.push(1); } let mut index_flag: usize = 0; let mut flag: Mode = Mode::Default; let mut backslash_flag: bool = false; let mut temp_string: Vec = vec![]; for (index, character) in file_contents.bytes().enumerate() { if backslash_flag { // Push a newline or tab character when there's a \n or \t // Otherwise, just push the raw sequence backslash(&mut bytes, character); backslash_flag = false; } match flag { Mode::Default => default_flag(&mut bytes, &mut temp_string, &mut flag, &mut index_flag, character, index), Mode::String => // in a string { match character { 39 | 34 => { temp_string.push(8); bytes.append(&mut temp_string); flag = Mode::Default; }, 92 => backslash_flag = true, _ => temp_string.push(character), } }, Mode::Name => // in a name { match character { 41 => { temp_string.push(4); bytes.append(&mut temp_string); // ) for name end temp_string = vec![]; flag = Mode::Default; }, 92 => backslash_flag = true, _ => temp_string.push(character), } }, Mode::Import => // in import { if character == 58 { file_list.push(ROOT_DIR.join(&file_contents[index_flag..index])); let (new_bytes, mut new_file_list) = read_file ( &file_contents[index_flag..index], depth+1 ); file_list.append(&mut new_file_list); for byte in &new_bytes { bytes.push(*byte); } flag = Mode::Default; } }, } } if depth == 0 { bytes.push(2); } (bytes, file_list) // return }