use flate2::write::GzEncoder;
use std::{fs::File, io::Write};
use crate::app::compass::{
response::response_output_format::ResponseOutputFormat, CompassAppError,
};
pub enum InternalWriter {
File { file: File },
GzippedFile { encoder: GzEncoder<File> },
}
impl InternalWriter {
pub fn write_header(
&mut self,
format: &ResponseOutputFormat,
) -> core::result::Result<(), CompassAppError> {
let file_is_empty = self.is_empty()?;
if file_is_empty {
let header = format.generate_header().unwrap_or_else(|| String::from(""));
self.write(header.as_bytes()).map(|_| {}).map_err(|e| {
CompassAppError::InternalError(format!("Failure writing header to file: {e}"))
})?;
}
Ok(())
}
pub fn is_empty(&self) -> Result<bool, CompassAppError> {
match self {
InternalWriter::File { file } => is_empty(file),
InternalWriter::GzippedFile { encoder } => is_empty(encoder.get_ref()),
}
}
pub fn finish(&mut self) -> core::result::Result<(), CompassAppError> {
match self {
InternalWriter::File { ref mut file } => {
file.flush().map_err(|e| {
CompassAppError::InternalError(format!("failure flushing output {e}"))
})?;
Ok(())
}
InternalWriter::GzippedFile { ref mut encoder } => {
let _ = encoder.flush();
encoder.try_finish().map_err(|e| {
CompassAppError::InternalError(format!("failure finishing encoded output {e}"))
})?;
Ok(())
}
}
}
}
impl Write for InternalWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match self {
InternalWriter::File { file } => file.write(buf),
InternalWriter::GzippedFile { encoder } => encoder.write(buf),
}
}
fn flush(&mut self) -> std::io::Result<()> {
match self {
InternalWriter::File { file } => file.flush(),
InternalWriter::GzippedFile { encoder } => encoder.flush(),
}
}
}
fn is_empty(file: &File) -> Result<bool, CompassAppError> {
let m = file.metadata().map_err(|e| {
CompassAppError::InternalError(format!("failure inspecting output file metadata: {e}"))
})?;
Ok(m.len() == 0)
}