use std::borrow::Cow;
use std::sync::Arc;
use std::sync::Mutex;
use crate::error::DatabaseError;
use crate::file::File;
use crate::file::FileId;
#[derive(Debug)]
pub enum Change {
Add(File),
Update(FileId, Cow<'static, str>),
Delete(FileId),
}
#[derive(Clone, Debug)]
pub struct ChangeLog {
pub(crate) changes: Arc<Mutex<Vec<Change>>>,
}
impl Default for ChangeLog {
fn default() -> Self {
Self::new()
}
}
impl ChangeLog {
pub fn new() -> Self {
Self { changes: Arc::new(Mutex::new(Vec::new())) }
}
pub fn add(&self, file: File) -> Result<(), DatabaseError> {
self.changes.lock().map_err(|_| DatabaseError::PoisonedLogMutex)?.push(Change::Add(file));
Ok(())
}
pub fn update(&self, id: FileId, new_contents: Cow<'static, str>) -> Result<(), DatabaseError> {
self.changes.lock().map_err(|_| DatabaseError::PoisonedLogMutex)?.push(Change::Update(id, new_contents));
Ok(())
}
pub fn delete(&self, id: FileId) -> Result<(), DatabaseError> {
self.changes.lock().map_err(|_| DatabaseError::PoisonedLogMutex)?.push(Change::Delete(id));
Ok(())
}
pub fn into_inner(self) -> Result<Vec<Change>, DatabaseError> {
match Arc::try_unwrap(self.changes) {
Ok(mutex) => mutex.into_inner().map_err(|_| DatabaseError::PoisonedLogMutex),
Err(_) => Err(DatabaseError::ChangeLogInUse),
}
}
}