77 lines
2.5 KiB
Rust
77 lines
2.5 KiB
Rust
|
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<TrashFile>,
|
||
|
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<Self, TrashManifestError> {
|
||
|
let mut contents = String::new();
|
||
|
manifest.read_to_string(&mut contents)?;
|
||
|
manifest.rewind()?;
|
||
|
|
||
|
if contents.len() < 2 {
|
||
|
contents = "[]".to_string();
|
||
|
}
|
||
|
let files: Vec<TrashFile> = 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<TrashFile> {
|
||
|
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<TrashFile> {
|
||
|
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, TrashManifestError> {
|
||
|
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, TrashManifestError> {
|
||
|
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),
|
||
|
}
|