use alloc::string::String;
use alloc::vec::Vec;
use thiserror_no_std::Error;
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum TrashError {
#[error("Dataset not found: {0}")]
DatasetNotFound(String),
#[error("Trash entry not found: {0}")]
EntryNotFound(u64),
#[error("Target path already exists: {0}")]
TargetExists(String),
#[error("IO error: {0}")]
IoError(String),
#[error("Path not found: {0}")]
PathNotFound(String),
#[error("Trash is disabled")]
TrashDisabled,
#[error("Permission denied")]
PermissionDenied,
}
#[derive(Debug, Clone)]
pub struct TrashEntry {
pub original_path: String,
pub trash_id: u64,
pub deleted_at: u64,
pub size: u64,
pub deleted_by: u32,
pub expires_at: u64,
pub is_directory: bool,
}
#[derive(Debug, Clone)]
pub struct TrashConfig {
pub enabled: bool,
pub retention_seconds: u64,
pub max_size: u64,
pub max_percent: u8,
pub auto_purge: bool,
pub purge_threshold: u8,
pub secure_delete: bool,
}
impl Default for TrashConfig {
fn default() -> Self {
Self {
enabled: true,
retention_seconds: 30 * 24 * 3600, max_size: 0, max_percent: 10, auto_purge: true,
purge_threshold: 90, secure_delete: false, }
}
}
#[derive(Debug, Clone)]
pub enum TrashFilter {
All,
OlderThan(u64),
Expired,
LargerThan(u64),
ById(u64),
ByPattern(String),
}
#[derive(Debug, Clone, Default)]
pub struct TrashEmptyResult {
pub deleted_count: u64,
pub deleted_bytes: u64,
pub failed_count: u64,
}
#[derive(Debug, Clone, Default)]
pub struct TrashMetadata {
pub entries: Vec<TrashEntry>,
pub next_id: u64,
pub total_size: u64,
}
impl TrashMetadata {
pub fn new() -> Self {
Self {
entries: Vec::new(),
next_id: 1,
total_size: 0,
}
}
pub fn add_entry(&mut self, entry: TrashEntry) {
self.total_size += entry.size;
self.entries.push(entry);
}
pub fn remove_entry(&mut self, trash_id: u64) -> Option<TrashEntry> {
if let Some(pos) = self.entries.iter().position(|e| e.trash_id == trash_id) {
let entry = self.entries.remove(pos);
self.total_size = self.total_size.saturating_sub(entry.size);
Some(entry)
} else {
None
}
}
pub fn find_entry(&self, trash_id: u64) -> Option<&TrashEntry> {
self.entries.iter().find(|e| e.trash_id == trash_id)
}
pub fn expired_entries(&self, current_time: u64) -> Vec<&TrashEntry> {
self.entries
.iter()
.filter(|e| e.expires_at > 0 && e.expires_at <= current_time)
.collect()
}
pub fn oldest_entries(&self) -> Vec<&TrashEntry> {
let mut entries: Vec<&TrashEntry> = self.entries.iter().collect();
entries.sort_by_key(|e| e.deleted_at);
entries
}
pub fn allocate_id(&mut self) -> u64 {
let id = self.next_id;
self.next_id += 1;
id
}
}