Simple tool for automatic file management
1use std::path::Path;
2
3use async_trait::async_trait;
4use serde::Deserialize;
5use tokio::fs;
6
7use crate::pattern::Pattern;
8
9#[typetag::deserialize(tag = "type")]
10#[async_trait]
11pub trait Filter: std::fmt::Debug {
12 async fn matches(&self, path: &Path) -> bool;
13}
14
15#[derive(Debug, Deserialize)]
16pub struct Name(Pattern);
17
18#[typetag::deserialize(name = "name")]
19#[async_trait]
20impl Filter for Name {
21 async fn matches(&self, path: &Path) -> bool {
22 self.0.matches(path)
23 }
24}
25
26#[derive(Debug, Deserialize)]
27pub struct Size {
28 size: u64,
29 #[serde(with = "Ordering")]
30 ordering: std::cmp::Ordering,
31}
32
33#[derive(Deserialize)]
34#[serde(remote = "std::cmp::Ordering")]
35enum Ordering {
36 Less,
37 Equal,
38 Greater,
39}
40
41#[typetag::deserialize(name = "size")]
42#[async_trait]
43impl Filter for Size {
44 async fn matches(&self, path: &Path) -> bool {
45 with_metadata(path, |metadata| {
46 let len = metadata.len();
47
48 self.size.cmp(&len) == self.ordering
49 })
50 .await
51 }
52}
53
54#[derive(Debug, Deserialize)]
55pub enum FileType {
56 Dir,
57 File,
58 Symlink,
59}
60
61#[typetag::deserialize(name = "file_type")]
62#[async_trait]
63impl Filter for FileType {
64 async fn matches(&self, path: &Path) -> bool {
65 use FileType::*;
66
67 with_metadata(path, |metadata| {
68 let ft = metadata.file_type();
69
70 match *self {
71 Dir => ft.is_dir(),
72 File => ft.is_file(),
73 Symlink => ft.is_symlink(),
74 }
75 })
76 .await
77 }
78}
79
80async fn with_metadata<F>(path: &Path, fun: F) -> bool
81where
82 F: FnOnce(std::fs::Metadata) -> bool,
83{
84 fs::metadata(path).await.map(fun).unwrap_or(false)
85}
86
87#[derive(Debug, Deserialize)]
88pub enum Magic {
89 Mime(String),
90 Bytes(Box<[u8]>),
91}