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}