use crate::error::Error;
use crate::format::FileFormat;
use crate::fs::File;
use super::{FileManager, FileLock, FileMode};
use std::io;
use std::path::Path;
#[derive(Debug)]
pub struct StandardManager<Format> {
format: Format,
options: StandardManagerOptions,
file: File
}
impl<T, Format> FileManager<T> for StandardManager<Format>
where Format: FileFormat<T> {
type Format = Format;
type Options = StandardManagerOptions;
type Error = Error<<Self::Format as FileFormat<T>>::FormatError>;
fn open<P: AsRef<Path>>(
path: P, format: Self::Format, options: Self::Options
) -> Result<Self, Self::Error> {
let file = options.open(path.as_ref())?;
Ok(StandardManager { format, options, file })
}
fn read(&mut self) -> Result<T, Self::Error> {
self.options.mode.must_read()?;
super::read(&self.format, &self.file)
}
fn write(&mut self, value: &T) -> Result<(), Self::Error> {
self.options.mode.must_write()?;
super::write(&self.format, &self.file, value)
}
fn into_inner(self) -> Result<(Format, Self::Options), Self::Error> {
self.options.lock.unlock(&self.file)?;
Ok((self.format, self.options))
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Default)]
pub struct StandardManagerOptions {
pub lock: FileLock,
pub mode: FileMode
}
impl StandardManagerOptions {
pub const fn new() -> Self {
Self::from_lock_and_mode(FileLock::None, FileMode::Writable)
}
pub const fn from_lock_and_mode(lock: FileLock, mode: FileMode) -> Self {
StandardManagerOptions { lock, mode }
}
pub const fn with_lock(mut self, lock: FileLock) -> Self {
self.lock = lock;
self
}
pub const fn with_mode(mut self, mode: FileMode) -> Self {
self.mode = mode;
self
}
pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
let file = self.mode.open(path.as_ref())?;
self.lock.lock(&file)?;
Ok(file)
}
pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
let file = self.mode.create(path.as_ref())?;
self.lock.lock(&file)?;
Ok(file)
}
pub fn create_new<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
let file = self.mode.create_new(path.as_ref())?;
self.lock.lock(&file)?;
Ok(file)
}
pub const UNLOCKED_READONLY: Self = StandardManagerOptions::from_lock_and_mode(FileLock::None, FileMode::Readonly);
pub const UNLOCKED_WRITABLE: Self = StandardManagerOptions::from_lock_and_mode(FileLock::None, FileMode::Writable);
pub const LOCKED_READONLY: Self = StandardManagerOptions::from_lock_and_mode(FileLock::Shared, FileMode::Readonly);
pub const LOCKED_WRITABLE: Self = StandardManagerOptions::from_lock_and_mode(FileLock::Exclusive, FileMode::Writable);
}