use crate::error::{ParcodeError, Result};
use std::io::{BufWriter, Write};
use std::sync::Mutex;
#[cfg(not(target_arch = "wasm32"))]
use std::fs::File;
#[cfg(not(target_arch = "wasm32"))]
use std::path::Path;
const WRITE_BUFFER_SIZE: usize = 16 * 1024 * 1024;
#[derive(Debug)]
pub struct SeqWriter<W>
where
W: Write,
{
inner: Mutex<WriterState<W>>,
}
#[derive(Debug)]
struct WriterState<W>
where
W: Write,
{
writer: BufWriter<W>,
current_offset: u64,
}
impl<W> SeqWriter<W>
where
W: Write + Send,
{
pub fn new(writer: W) -> Self {
Self {
inner: Mutex::new(WriterState {
writer: BufWriter::with_capacity(WRITE_BUFFER_SIZE, writer),
current_offset: 0,
}),
}
}
pub fn write_all(&self, buffer: &[u8]) -> Result<u64> {
let mut state = self
.inner
.lock()
.map_err(|_| ParcodeError::Internal("Writer mutex poisoned".into()))?;
let start_offset = state.current_offset;
state.writer.write_all(buffer)?;
state.current_offset += buffer.len() as u64;
Ok(start_offset)
}
pub fn flush(&self) -> Result<()> {
let mut state = self
.inner
.lock()
.map_err(|_| ParcodeError::Internal("Writer mutex poisoned".into()))?;
state.writer.flush()?;
Ok(())
}
pub fn into_inner(self) -> Result<BufWriter<W>> {
let state = self.inner.into_inner().map_err(|_| {
ParcodeError::Internal("Writer mutex poisoned during consumption".into())
})?;
Ok(state.writer)
}
}
#[cfg(not(target_arch = "wasm32"))]
impl SeqWriter<File> {
pub fn create(path: &Path) -> Result<Self> {
let file = File::create(path)?;
Ok(Self::new(file))
}
}