Simplify read_file

This commit is contained in:
Andrew 2025-08-23 09:01:15 +12:00
parent c4342cb073
commit 6e3b64d8c5
3 changed files with 12 additions and 45 deletions

View file

@ -2,7 +2,7 @@ use std::{error::Error, fmt};
use crate::colors::{BitDepth, ColorType};
#[derive(Debug, Clone)]
#[derive(Debug)]
#[non_exhaustive]
pub enum PngError {
APNGOutOfOrder,
@ -15,7 +15,9 @@ pub enum PngError {
InvalidData,
InvalidDepthForType(BitDepth, ColorType),
NotPNG,
ReadFailed(String, std::io::Error),
TruncatedData,
WriteFailed(String, std::io::Error),
Other(Box<str>),
}
@ -47,9 +49,11 @@ impl fmt::Display for PngError {
write!(f, "Invalid bit depth {d} for color type {c}")
}
PngError::NotPNG => f.write_str("Invalid header detected; Not a PNG file"),
PngError::ReadFailed(ref s, ref e) => write!(f, "Failed to read from {s}: {e}"),
PngError::TruncatedData => {
f.write_str("Missing data in the file; the file is truncated")
}
PngError::WriteFailed(ref s, ref e) => write!(f, "Failed to write to {s}: {e}"),
PngError::Other(ref s) => f.write_str(s),
}
}

View file

@ -221,7 +221,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
let mut data = Vec::new();
stdin()
.read_to_end(&mut data)
.map_err(|e| PngError::new(&format!("Error reading stdin: {e}")))?;
.map_err(|e| PngError::ReadFailed("stdin".into(), e))?;
data
}
};
@ -270,20 +270,15 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
let mut buffer = BufWriter::new(stdout());
buffer
.write_all(&optimized_output)
.map_err(|e| PngError::new(&format!("Unable to write to stdout: {e}")))?;
.map_err(|e| PngError::WriteFailed("stdout".into(), e))?;
}
(OutFile::Path { path, .. }, _) => {
let output_path = path
.as_ref()
.map(|p| p.as_path())
.unwrap_or_else(|| input.path().unwrap());
let out_file = File::create(output_path).map_err(|err| {
PngError::new(&format!(
"Unable to write to file {}: {}",
output_path.display(),
err
))
})?;
let out_file = File::create(output_path)
.map_err(|err| PngError::WriteFailed(output_path.display().to_string(), err))?;
if let Some(metadata_input) = &opt_metadata_preserved {
copy_permissions(metadata_input, &out_file)?;
}
@ -293,13 +288,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
.write_all(&optimized_output)
// flush BufWriter so IO errors don't get swallowed silently on close() by drop!
.and_then(|()| buffer.flush())
.map_err(|e| {
PngError::new(&format!(
"Unable to write to {}: {}",
output_path.display(),
e
))
})?;
.map_err(|e| PngError::WriteFailed(output_path.display().to_string(), e))?;
// force drop and thereby closing of file handle before modifying any timestamp
std::mem::drop(buffer);
if let Some(metadata_input) = &opt_metadata_preserved {

View file

@ -1,9 +1,4 @@
use std::{
fs::File,
io::{BufReader, Read, Write},
path::Path,
sync::Arc,
};
use std::{fs, io::Write, path::Path, sync::Arc};
use bitvec::bitarr;
use libdeflater::{CompressionLvl, Compressor};
@ -62,28 +57,7 @@ impl PngData {
}
pub fn read_file(filepath: &Path) -> Result<Vec<u8>, PngError> {
let file = match File::open(filepath) {
Ok(f) => f,
Err(_) => return Err(PngError::new("Failed to open file for reading")),
};
let file_len = file.metadata().map(|m| m.len() as usize).unwrap_or(0);
let mut reader = BufReader::new(file);
// Check file for PNG header
let mut header = [0; 8];
if reader.read_exact(&mut header).is_err() {
return Err(PngError::new("Not a PNG file: too small"));
}
if !file_header_is_valid(&header) {
return Err(PngError::new("Invalid PNG header detected"));
}
// Read raw png data into memory
let mut byte_data: Vec<u8> = Vec::with_capacity(file_len);
byte_data.extend_from_slice(&header);
match reader.read_to_end(&mut byte_data) {
Ok(_) => (),
Err(_) => return Err(PngError::new("Failed to read from file")),
}
Ok(byte_data)
fs::read(filepath).map_err(|e| PngError::ReadFailed(filepath.display().to_string(), e))
}
/// Create a new `PngData` struct by reading a slice