unistore_watcher/
event.rs1use crate::deps::{EventKind, NotifyEvent, PathBuf};
8
9#[derive(Debug, Clone)]
11pub enum FileEvent {
12 Created(PathBuf),
14
15 Modified(PathBuf),
17
18 Deleted(PathBuf),
20
21 Renamed { from: PathBuf, to: PathBuf },
23
24 Accessed(PathBuf),
26
27 Other { kind: String, paths: Vec<PathBuf> },
29}
30
31impl FileEvent {
32 pub fn from_notify(event: NotifyEvent) -> Option<Self> {
34 let paths = event.paths;
35
36 match event.kind {
37 EventKind::Create(_) => paths.into_iter().next().map(FileEvent::Created),
38
39 EventKind::Modify(_) => paths.into_iter().next().map(FileEvent::Modified),
40
41 EventKind::Remove(_) => paths.into_iter().next().map(FileEvent::Deleted),
42
43 EventKind::Access(_) => paths.into_iter().next().map(FileEvent::Accessed),
44
45 EventKind::Other => Some(FileEvent::Other {
46 kind: "other".to_string(),
47 paths,
48 }),
49
50 _ => None,
51 }
52 }
53
54 pub fn path(&self) -> Option<&PathBuf> {
56 match self {
57 FileEvent::Created(p) => Some(p),
58 FileEvent::Modified(p) => Some(p),
59 FileEvent::Deleted(p) => Some(p),
60 FileEvent::Renamed { to, .. } => Some(to),
61 FileEvent::Accessed(p) => Some(p),
62 FileEvent::Other { paths, .. } => paths.first(),
63 }
64 }
65
66 pub fn paths(&self) -> Vec<&PathBuf> {
68 match self {
69 FileEvent::Created(p) => vec![p],
70 FileEvent::Modified(p) => vec![p],
71 FileEvent::Deleted(p) => vec![p],
72 FileEvent::Renamed { from, to } => vec![from, to],
73 FileEvent::Accessed(p) => vec![p],
74 FileEvent::Other { paths, .. } => paths.iter().collect(),
75 }
76 }
77
78 pub fn is_created(&self) -> bool {
80 matches!(self, FileEvent::Created(_))
81 }
82
83 pub fn is_modified(&self) -> bool {
85 matches!(self, FileEvent::Modified(_))
86 }
87
88 pub fn is_deleted(&self) -> bool {
90 matches!(self, FileEvent::Deleted(_))
91 }
92
93 pub fn is_renamed(&self) -> bool {
95 matches!(self, FileEvent::Renamed { .. })
96 }
97}
98
99impl std::fmt::Display for FileEvent {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 match self {
102 FileEvent::Created(p) => write!(f, "创建: {}", p.display()),
103 FileEvent::Modified(p) => write!(f, "修改: {}", p.display()),
104 FileEvent::Deleted(p) => write!(f, "删除: {}", p.display()),
105 FileEvent::Renamed { from, to } => {
106 write!(f, "重命名: {} -> {}", from.display(), to.display())
107 }
108 FileEvent::Accessed(p) => write!(f, "访问: {}", p.display()),
109 FileEvent::Other { kind, paths } => {
110 write!(f, "其他({}): {:?}", kind, paths)
111 }
112 }
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_event_path() {
122 let event = FileEvent::Created(PathBuf::from("/tmp/test.txt"));
123 assert_eq!(event.path(), Some(&PathBuf::from("/tmp/test.txt")));
124 assert!(event.is_created());
125 }
126
127 #[test]
128 fn test_renamed_paths() {
129 let event = FileEvent::Renamed {
130 from: PathBuf::from("/tmp/old.txt"),
131 to: PathBuf::from("/tmp/new.txt"),
132 };
133 assert_eq!(event.paths().len(), 2);
134 assert!(event.is_renamed());
135 }
136
137 #[test]
138 fn test_display() {
139 let event = FileEvent::Modified(PathBuf::from("/tmp/test.txt"));
140 let display = format!("{}", event);
141 assert!(display.contains("修改"));
142 }
143}