Simplify read_file
This commit is contained in:
parent
c4342cb073
commit
6e3b64d8c5
3 changed files with 12 additions and 45 deletions
|
|
@ -2,7 +2,7 @@ use std::{error::Error, fmt};
|
||||||
|
|
||||||
use crate::colors::{BitDepth, ColorType};
|
use crate::colors::{BitDepth, ColorType};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum PngError {
|
pub enum PngError {
|
||||||
APNGOutOfOrder,
|
APNGOutOfOrder,
|
||||||
|
|
@ -15,7 +15,9 @@ pub enum PngError {
|
||||||
InvalidData,
|
InvalidData,
|
||||||
InvalidDepthForType(BitDepth, ColorType),
|
InvalidDepthForType(BitDepth, ColorType),
|
||||||
NotPNG,
|
NotPNG,
|
||||||
|
ReadFailed(String, std::io::Error),
|
||||||
TruncatedData,
|
TruncatedData,
|
||||||
|
WriteFailed(String, std::io::Error),
|
||||||
Other(Box<str>),
|
Other(Box<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,9 +49,11 @@ impl fmt::Display for PngError {
|
||||||
write!(f, "Invalid bit depth {d} for color type {c}")
|
write!(f, "Invalid bit depth {d} for color type {c}")
|
||||||
}
|
}
|
||||||
PngError::NotPNG => f.write_str("Invalid header detected; Not a PNG file"),
|
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 => {
|
PngError::TruncatedData => {
|
||||||
f.write_str("Missing data in the file; the file is truncated")
|
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),
|
PngError::Other(ref s) => f.write_str(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/lib.rs
21
src/lib.rs
|
|
@ -221,7 +221,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
stdin()
|
stdin()
|
||||||
.read_to_end(&mut data)
|
.read_to_end(&mut data)
|
||||||
.map_err(|e| PngError::new(&format!("Error reading stdin: {e}")))?;
|
.map_err(|e| PngError::ReadFailed("stdin".into(), e))?;
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -270,20 +270,15 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
let mut buffer = BufWriter::new(stdout());
|
let mut buffer = BufWriter::new(stdout());
|
||||||
buffer
|
buffer
|
||||||
.write_all(&optimized_output)
|
.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, .. }, _) => {
|
(OutFile::Path { path, .. }, _) => {
|
||||||
let output_path = path
|
let output_path = path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| p.as_path())
|
.map(|p| p.as_path())
|
||||||
.unwrap_or_else(|| input.path().unwrap());
|
.unwrap_or_else(|| input.path().unwrap());
|
||||||
let out_file = File::create(output_path).map_err(|err| {
|
let out_file = File::create(output_path)
|
||||||
PngError::new(&format!(
|
.map_err(|err| PngError::WriteFailed(output_path.display().to_string(), err))?;
|
||||||
"Unable to write to file {}: {}",
|
|
||||||
output_path.display(),
|
|
||||||
err
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
if let Some(metadata_input) = &opt_metadata_preserved {
|
if let Some(metadata_input) = &opt_metadata_preserved {
|
||||||
copy_permissions(metadata_input, &out_file)?;
|
copy_permissions(metadata_input, &out_file)?;
|
||||||
}
|
}
|
||||||
|
|
@ -293,13 +288,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
||||||
.write_all(&optimized_output)
|
.write_all(&optimized_output)
|
||||||
// flush BufWriter so IO errors don't get swallowed silently on close() by drop!
|
// flush BufWriter so IO errors don't get swallowed silently on close() by drop!
|
||||||
.and_then(|()| buffer.flush())
|
.and_then(|()| buffer.flush())
|
||||||
.map_err(|e| {
|
.map_err(|e| PngError::WriteFailed(output_path.display().to_string(), e))?;
|
||||||
PngError::new(&format!(
|
|
||||||
"Unable to write to {}: {}",
|
|
||||||
output_path.display(),
|
|
||||||
e
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
// force drop and thereby closing of file handle before modifying any timestamp
|
// force drop and thereby closing of file handle before modifying any timestamp
|
||||||
std::mem::drop(buffer);
|
std::mem::drop(buffer);
|
||||||
if let Some(metadata_input) = &opt_metadata_preserved {
|
if let Some(metadata_input) = &opt_metadata_preserved {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
use std::{
|
use std::{fs, io::Write, path::Path, sync::Arc};
|
||||||
fs::File,
|
|
||||||
io::{BufReader, Read, Write},
|
|
||||||
path::Path,
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use bitvec::bitarr;
|
use bitvec::bitarr;
|
||||||
use libdeflater::{CompressionLvl, Compressor};
|
use libdeflater::{CompressionLvl, Compressor};
|
||||||
|
|
@ -62,28 +57,7 @@ impl PngData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_file(filepath: &Path) -> Result<Vec<u8>, PngError> {
|
pub fn read_file(filepath: &Path) -> Result<Vec<u8>, PngError> {
|
||||||
let file = match File::open(filepath) {
|
fs::read(filepath).map_err(|e| PngError::ReadFailed(filepath.display().to_string(), e))
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `PngData` struct by reading a slice
|
/// Create a new `PngData` struct by reading a slice
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue