use std::fs::File; use std::io::{Read, Seek, Write}; use std::path::PathBuf; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] pub struct TrashFile { pub name: String, pub origin: PathBuf, } pub struct Manifest { files: Vec, manifest: File, } impl Manifest { /// Creates a new Manifest from a .manifest.ron file. /// Expects File to be read and write. pub fn new(mut manifest: File) -> Result { let mut contents = String::new(); manifest.read_to_string(&mut contents)?; manifest.rewind()?; if contents.len() < 2 { contents = "[]".to_string(); } let files: Vec = ron::from_str(&contents)?; Ok(Self { files, manifest }) } /// Get a certain file from the manifest by it's name. pub fn get(&self, name: String) -> Option { self.files .iter() .find(|file| file.name == *name) .map(|file| file.clone()) } /// Get a clone of the underlying Vec of TrashFile. pub fn get_all(&self) -> Vec { self.files.clone() } /// Remove a file from the manifest by it's name. /// Consumes self and returns self back in a result to prevent inconsistencies /// between self and the actual manifest file in case of Err. pub fn remove(mut self, name: String) -> Result { self.files.retain(|file| file.name != name); let contents = ron::to_string(&self.files)?; self.manifest.set_len(0)?; self.manifest.rewind()?; write!(&mut self.manifest, "{}", contents)?; Ok(self) } /// Add a file to the manifest by it's name and path to origin. /// Consumes self and returns self back in a result to prevent inconsistencies /// between self and the actual manifest file in case of Err. pub fn add(mut self, name: String, origin: PathBuf) -> Result { self.files.push(TrashFile { name, origin }); dbg!(&self.files); let contents = ron::to_string(&self.files)?; self.manifest.set_len(0)?; self.manifest.rewind()?; write!(&mut self.manifest, "{}", contents)?; Ok(self) } } #[derive(thiserror::Error, Debug)] pub enum TrashManifestError { #[error("Could not read manifest file")] IoError(#[from] std::io::Error), #[error("Could not serialize or deserialize manifest file")] SerializationError(#[from] ron::Error), }