forked from Cutieguwu/raven
100 lines
2.4 KiB
Rust
100 lines
2.4 KiB
Rust
use std::collections::HashSet;
|
|
use std::collections::hash_set::Iter;
|
|
use std::fs::OpenOptions;
|
|
use std::hash::Hash;
|
|
use std::io::Read;
|
|
use std::path::Path;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use path::{PathHandled, PathHandler};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::Error;
|
|
|
|
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
|
pub struct Lock<T> {
|
|
#[serde(skip_deserializing, skip_serializing)]
|
|
ph: Option<Arc<Mutex<PathHandler>>>,
|
|
inner: HashSet<T>,
|
|
}
|
|
|
|
impl<T> Lock<T>
|
|
where
|
|
T: Lockable + Status + Deserialize<'de>,
|
|
{
|
|
pub fn new(ph: Arc<Mutex<PathHandler>>, inner: HashSet<T>) -> Self {
|
|
Self {
|
|
ph: Some(ph),
|
|
inner,
|
|
}
|
|
}
|
|
|
|
pub fn load<P>(ph: Arc<Mutex<PathHandler>>, path: P) -> crate::Result<Self>
|
|
where
|
|
P: AsRef<Path>,
|
|
{
|
|
let mut path = path.as_ref().to_path_buf();
|
|
if path.is_relative() {
|
|
path = path.canonicalize()?;
|
|
}
|
|
|
|
let mut buf = Vec::new();
|
|
OpenOptions::new()
|
|
.read(true)
|
|
.open(path)?
|
|
.read_to_end(&mut buf)?;
|
|
|
|
let lock: Lock<T> = toml::from_slice(buf.as_slice())?;
|
|
|
|
Ok(lock)
|
|
}
|
|
|
|
pub fn update(&mut self) -> crate::Result<()> {
|
|
let ph = self.ph.as_ref().ok_or(Error::MissingPathHandler)?.clone();
|
|
|
|
self.inner = self
|
|
.inner
|
|
.clone()
|
|
.into_iter()
|
|
.filter_map(|mut item| {
|
|
let item = item.with_path_handler(Arc::clone(&ph));
|
|
|
|
// If the class is up-to-date and no errors occurred during the check
|
|
if item.is_updated().is_ok_and(|b| b == true) {
|
|
Some(item.to_owned())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn set_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) {
|
|
self.ph = Some(ph);
|
|
}
|
|
|
|
pub fn with_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) -> &mut Self {
|
|
self.ph = Some(ph);
|
|
self
|
|
}
|
|
|
|
/// Iterates over the entries in `NestLock`.
|
|
pub fn iter(&self) -> Iter<'_, T> {
|
|
self.inner.iter()
|
|
}
|
|
|
|
pub fn insert(&mut self, class: T) -> bool {
|
|
self.inner.insert(class)
|
|
}
|
|
}
|
|
|
|
pub trait Lockable: Hash + Eq + Clone + PathHandled {}
|
|
|
|
trait Status {
|
|
type Error;
|
|
|
|
fn is_updated(&self) -> Result<bool, Self::Error>;
|
|
}
|