kaish_kernel/
trash_system.rs1use std::path::Path;
7
8use async_trait::async_trait;
9
10use crate::trash::{TrashBackend, TrashEntry, TrashError, TrashId, find_restore_match};
11
12pub struct SystemTrash;
14
15impl SystemTrash {
16 fn to_entry(item: &trash::TrashItem) -> TrashEntry {
18 TrashEntry {
19 id: TrashId::system(item.id.clone()),
20 name: item.name.to_string_lossy().to_string(),
21 original_path: item.original_parent.join(&item.name),
22 deleted_at: item.time_deleted,
23 }
24 }
25}
26
27async fn spawn_trash<F, T>(op: F) -> Result<T, TrashError>
29where
30 F: FnOnce() -> Result<T, trash::Error> + Send + 'static,
31 T: Send + 'static,
32{
33 match tokio::task::spawn_blocking(op).await {
34 Ok(Ok(v)) => Ok(v),
35 Ok(Err(e)) => Err(TrashError::Backend(e.to_string())),
36 Err(e) => Err(TrashError::Join(e.to_string())),
37 }
38}
39
40#[async_trait]
41impl TrashBackend for SystemTrash {
42 async fn trash(&self, path: &Path) -> Result<(), TrashError> {
43 let p = path.to_owned();
44 spawn_trash(move || trash::delete(&p)).await
45 }
46
47 async fn list(&self, filter: Option<&str>) -> Result<Vec<TrashEntry>, TrashError> {
48 let items = spawn_trash(trash::os_limited::list).await?;
49 let filter_owned = filter.map(|s| s.to_owned());
50
51 let entries: Vec<TrashEntry> = items
52 .iter()
53 .filter(|item| {
54 if let Some(ref f) = filter_owned {
55 item.name.to_string_lossy().contains(f.as_str())
56 } else {
57 true
58 }
59 })
60 .map(Self::to_entry)
61 .collect();
62
63 Ok(entries)
64 }
65
66 async fn find_by_name(&self, name: &str) -> Result<Vec<TrashEntry>, TrashError> {
67 let items = spawn_trash(trash::os_limited::list).await?;
68
69 let named_items: Vec<(String, &trash::TrashItem)> = items
70 .iter()
71 .map(|item| (item.name.to_string_lossy().to_string(), item))
72 .collect();
73
74 find_restore_match(named_items, name)
75 .map(|matched| matched.into_iter().map(Self::to_entry).collect())
76 .map_err(TrashError::Backend)
77 }
78
79 async fn restore(&self, entries: Vec<TrashEntry>) -> Result<(), TrashError> {
80 let items: Vec<trash::TrashItem> = entries
82 .into_iter()
83 .map(|entry| {
84 let crate::trash::TrashIdInner::System(id) = entry.id.0;
85 trash::TrashItem {
86 id,
87 name: entry.name.into(),
88 original_parent: entry
89 .original_path
90 .parent()
91 .unwrap_or(Path::new("/"))
92 .to_path_buf(),
93 time_deleted: entry.deleted_at,
94 }
95 })
96 .collect();
97
98 spawn_trash(move || trash::os_limited::restore_all(items)).await
99 }
100
101 async fn purge_all(&self) -> Result<usize, TrashError> {
102 let items = spawn_trash(trash::os_limited::list).await?;
103 if items.is_empty() {
104 return Ok(0);
105 }
106 let count = items.len();
107 spawn_trash(move || trash::os_limited::purge_all(items)).await?;
108 Ok(count)
109 }
110}