1use crate::{EventFlag, FSEventStreamEventId, ScanType};
2use std::{
3 ffi::{CStr, OsStr},
4 os::unix::ffi::OsStrExt,
5 path::{Path, PathBuf},
6};
7
8#[derive(Debug)]
9pub struct FsEvent {
10 pub path: PathBuf,
12 pub flag: EventFlag,
14 pub id: FSEventStreamEventId,
16}
17
18impl FsEvent {
19 pub(crate) unsafe fn from_raw(path: *const i8, flag: u32, id: u64) -> Self {
20 let path = unsafe { CStr::from_ptr(path) };
21 let path = OsStr::from_bytes(path.to_bytes());
22 let path = PathBuf::from(path);
23 let flag = EventFlag::from_bits_truncate(flag);
24 FsEvent { path, flag, id }
25 }
26
27 pub fn should_rescan(&self, root: &Path) -> bool {
28 match self.flag.scan_type() {
29 ScanType::ReScan => true,
30 ScanType::SingleNode | ScanType::Folder if self.path == root => true,
31 ScanType::SingleNode | ScanType::Folder | ScanType::Nop => false,
32 }
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use std::path::PathBuf;
40
41 #[test]
42 fn test_should_rescan() {
43 let root = std::path::Path::new("/root");
44
45 let event = FsEvent {
47 path: PathBuf::from("/root/file"),
48 flag: EventFlag::RootChanged,
49 id: 1,
50 };
51 assert!(event.should_rescan(root));
52
53 let event = FsEvent {
55 path: PathBuf::from("/root"),
56 flag: EventFlag::ItemModified | EventFlag::ItemIsFile,
57 id: 1,
58 };
59 assert!(event.should_rescan(root));
60
61 let event = FsEvent {
63 path: PathBuf::from("/root/sub/file"),
64 flag: EventFlag::ItemModified | EventFlag::ItemIsFile,
65 id: 1,
66 };
67 assert!(!event.should_rescan(root));
68
69 let event = FsEvent {
71 path: PathBuf::from("/root/file"),
72 flag: EventFlag::HistoryDone,
73 id: 1,
74 };
75 assert!(!event.should_rescan(root));
76 }
77}