use std::{
fs,
io::{Error, Read, Seek, SeekFrom, Write},
mem::{self, ManuallyDrop},
};
use crate::{metadata::Metadata, Diskit};
#[allow(missing_docs)]
#[allow(clippy::module_name_repetitions)]
#[derive(Debug)]
pub struct FileInner
{
pub file: Option<fs::File>,
pub val: usize,
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct File<D>
where
D: Diskit,
{
pub inner: FileInner,
pub diskit: D,
}
impl<D> Read for File<D>
where
D: Diskit,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>
{
self.diskit.read_inner(&self.inner, buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
{
self.diskit.read_to_end_inner(&mut self.inner, buf)
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
{
self.diskit.read_to_string_inner(&mut self.inner, buf)
}
}
impl<D> Write for File<D>
where
D: Diskit,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Error>
{
self.diskit.write_inner(&mut self.inner, buf)
}
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
{
self.diskit.write_all_inner(&mut self.inner, buf)
}
fn flush(&mut self) -> std::io::Result<()>
{
self.diskit.flush_inner(&mut self.inner)
}
}
impl<D> Seek for File<D>
where
D: Diskit,
{
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>
{
self.diskit.seek_inner(&mut self.inner, pos)
}
}
impl<D> Drop for File<D>
where
D: Diskit,
{
fn drop(&mut self)
{
let diskit = self.diskit.clone();
let file = mem::replace(
&mut ManuallyDrop::new(self).inner,
FileInner { file: None, val: 0 },
);
let file_copy = (file.file.is_some(), file.val);
if let Err(err) = diskit.close_inner(file)
{
eprintln!("Error in closing file {file_copy:?}: {err:?}");
}
}
}
impl<D> File<D>
where
D: Diskit,
{
pub fn metadata(&self) -> Result<Metadata, Error>
{
self.diskit.metadata_inner(&self.inner)
}
pub fn close(self) -> Result<(), Error>
{
let diskit = self.diskit.clone();
diskit.close_inner(mem::replace(
&mut ManuallyDrop::new(self).inner,
FileInner { file: None, val: 0 },
))
}
}