use crate::persistence::error::{PersistenceError, PersistenceResult};
use std::io::{Read, Write};
use std::path::PathBuf;
pub trait Directory: Send + Sync {
fn create_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>>;
fn open_file(&self, path: &str) -> PersistenceResult<Box<dyn Read + Send>>;
fn exists(&self, path: &str) -> bool;
fn delete(&self, path: &str) -> PersistenceResult<()>;
fn atomic_rename(&self, from: &str, to: &str) -> PersistenceResult<()>;
fn create_dir_all(&self, path: &str) -> PersistenceResult<()>;
fn list_dir(&self, path: &str) -> PersistenceResult<Vec<String>>;
fn append_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>>;
fn atomic_write(&self, path: &str, data: &[u8]) -> PersistenceResult<()>;
fn file_path(&self, path: &str) -> Option<PathBuf>;
}
#[cfg(not(feature = "persistence"))]
fn disabled() -> PersistenceError {
PersistenceError::NotSupported("persistence feature disabled".to_string())
}
#[cfg(not(feature = "persistence"))]
#[derive(Debug, Default, Clone)]
pub struct MemoryDirectory;
#[cfg(not(feature = "persistence"))]
impl MemoryDirectory {
pub fn new() -> Self {
Self
}
}
#[cfg(not(feature = "persistence"))]
impl Directory for MemoryDirectory {
fn create_file(&self, _path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
Err(disabled())
}
fn open_file(&self, _path: &str) -> PersistenceResult<Box<dyn Read + Send>> {
Err(disabled())
}
fn exists(&self, _path: &str) -> bool {
false
}
fn delete(&self, _path: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn atomic_rename(&self, _from: &str, _to: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn create_dir_all(&self, _path: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn list_dir(&self, _path: &str) -> PersistenceResult<Vec<String>> {
Err(disabled())
}
fn append_file(&self, _path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
Err(disabled())
}
fn atomic_write(&self, _path: &str, _data: &[u8]) -> PersistenceResult<()> {
Err(disabled())
}
fn file_path(&self, _path: &str) -> Option<PathBuf> {
None
}
}
#[cfg(not(feature = "persistence"))]
#[derive(Debug, Default, Clone)]
pub struct FsDirectory;
#[cfg(not(feature = "persistence"))]
impl FsDirectory {
pub fn new(_root: impl Into<PathBuf>) -> PersistenceResult<Self> {
Err(disabled())
}
}
#[cfg(not(feature = "persistence"))]
impl Directory for FsDirectory {
fn create_file(&self, _path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
Err(disabled())
}
fn open_file(&self, _path: &str) -> PersistenceResult<Box<dyn Read + Send>> {
Err(disabled())
}
fn exists(&self, _path: &str) -> bool {
false
}
fn delete(&self, _path: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn atomic_rename(&self, _from: &str, _to: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn create_dir_all(&self, _path: &str) -> PersistenceResult<()> {
Err(disabled())
}
fn list_dir(&self, _path: &str) -> PersistenceResult<Vec<String>> {
Err(disabled())
}
fn append_file(&self, _path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
Err(disabled())
}
fn atomic_write(&self, _path: &str, _data: &[u8]) -> PersistenceResult<()> {
Err(disabled())
}
fn file_path(&self, _path: &str) -> Option<PathBuf> {
None
}
}
#[cfg(feature = "persistence")]
mod enabled {
use super::*;
use durability::storage::Directory as DurabilityDirectory;
#[derive(Clone, Default)]
pub struct MemoryDirectory {
inner: durability::storage::MemoryDirectory,
}
impl MemoryDirectory {
pub fn new() -> Self {
Self {
inner: durability::storage::MemoryDirectory::new(),
}
}
}
impl Directory for MemoryDirectory {
fn create_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
self.inner.create_file(path).map_err(PersistenceError::from)
}
fn open_file(&self, path: &str) -> PersistenceResult<Box<dyn Read + Send>> {
self.inner.open_file(path).map_err(PersistenceError::from)
}
fn exists(&self, path: &str) -> bool {
self.inner.exists(path)
}
fn delete(&self, path: &str) -> PersistenceResult<()> {
self.inner.delete(path).map_err(PersistenceError::from)
}
fn atomic_rename(&self, from: &str, to: &str) -> PersistenceResult<()> {
self.inner
.atomic_rename(from, to)
.map_err(PersistenceError::from)
}
fn create_dir_all(&self, path: &str) -> PersistenceResult<()> {
self.inner
.create_dir_all(path)
.map_err(PersistenceError::from)
}
fn list_dir(&self, path: &str) -> PersistenceResult<Vec<String>> {
self.inner.list_dir(path).map_err(PersistenceError::from)
}
fn append_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
self.inner.append_file(path).map_err(PersistenceError::from)
}
fn atomic_write(&self, path: &str, data: &[u8]) -> PersistenceResult<()> {
self.inner
.atomic_write(path, data)
.map_err(PersistenceError::from)
}
fn file_path(&self, path: &str) -> Option<PathBuf> {
self.inner.file_path(path)
}
}
pub struct FsDirectory {
root: PathBuf,
inner: durability::storage::FsDirectory,
}
impl FsDirectory {
pub fn new(root: impl Into<PathBuf>) -> PersistenceResult<Self> {
let root = root.into();
let inner = durability::storage::FsDirectory::new(root.clone())
.map_err(PersistenceError::from)?;
Ok(Self { root, inner })
}
pub fn root(&self) -> &PathBuf {
&self.root
}
}
impl Directory for FsDirectory {
fn create_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
self.inner.create_file(path).map_err(PersistenceError::from)
}
fn open_file(&self, path: &str) -> PersistenceResult<Box<dyn Read + Send>> {
self.inner.open_file(path).map_err(PersistenceError::from)
}
fn exists(&self, path: &str) -> bool {
self.inner.exists(path)
}
fn delete(&self, path: &str) -> PersistenceResult<()> {
self.inner.delete(path).map_err(PersistenceError::from)
}
fn atomic_rename(&self, from: &str, to: &str) -> PersistenceResult<()> {
self.inner
.atomic_rename(from, to)
.map_err(PersistenceError::from)
}
fn create_dir_all(&self, path: &str) -> PersistenceResult<()> {
self.inner
.create_dir_all(path)
.map_err(PersistenceError::from)
}
fn list_dir(&self, path: &str) -> PersistenceResult<Vec<String>> {
self.inner.list_dir(path).map_err(PersistenceError::from)
}
fn append_file(&self, path: &str) -> PersistenceResult<Box<dyn Write + Send>> {
self.inner.append_file(path).map_err(PersistenceError::from)
}
fn atomic_write(&self, path: &str, data: &[u8]) -> PersistenceResult<()> {
self.inner
.atomic_write(path, data)
.map_err(PersistenceError::from)
}
fn file_path(&self, path: &str) -> Option<PathBuf> {
self.inner.file_path(path)
}
}
pub use FsDirectory as PublicFsDirectory;
pub use MemoryDirectory as PublicMemoryDirectory;
}
#[cfg(feature = "persistence")]
pub use enabled::{PublicFsDirectory as FsDirectory, PublicMemoryDirectory as MemoryDirectory};