use crate::input;
use std::{error, fmt, io, path::PathBuf};
#[derive(Debug)]
pub enum Error {
InputFile { path: PathBuf, error: io::Error },
MissingInput,
ParseHeaders(csv::Error),
InsufficientInputColumns { pollinators: Vec<String> },
ReadRecord(csv::Error),
InvalidFieldValue(input::ParseFieldError),
MissingPlantIdent {
line_nr: usize,
},
DuplicatePlantIdent {
prev_occ_line_nr: usize,
line_nr: usize,
plant: String,
},
MissingData,
OutputFile { path: PathBuf, error: io::Error },
WriteRecord(csv::Error),
OutputData(io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::InputFile { path, error } => {
write!(f, "unable access input file '{}': {error}", path.display())
}
Error::MissingInput => {
f.write_str("expected either input file or piped input from stdin")
}
Error::ParseHeaders(error) => write!(f, "unable to retrieve input headers: {error}"),
Error::InsufficientInputColumns { pollinators } => {
let field = pollinators.len();
write!(
f,
"insufficient number of columns in input data: required \
at least two species of pollinators, found {field}"
)?;
if field > 0 {
write!(f, " ('{}')", pollinators[0])?;
}
Ok(())
}
Error::ReadRecord(error) => write!(f, "invalid input record: {error}"),
Error::InvalidFieldValue(error) => error.fmt(f),
Error::MissingPlantIdent { line_nr } => {
write!(f, "missing plant identifier at line {line_nr}")
}
Error::DuplicatePlantIdent {
line_nr: line,
prev_occ_line_nr,
plant,
} => {
write!(
f,
"duplicate plant ('{plant}') at line {line}, \
previous occurrence at line {prev_occ_line_nr}"
)
}
Error::MissingData => f.write_str(
"missing plant-pollinator interaction data, \
required at least one record",
),
Error::OutputFile { path, error } => write!(
f,
"unable to create output file '{}': {error}",
path.display()
),
Error::WriteRecord(error) => write!(f, "unable to write output record: {error}"),
Error::OutputData(error) => {
write!(f, "unable to write output data: {error}")
}
}
}
}
impl error::Error for Error {}
impl From<input::ParseFieldError> for Error {
fn from(error: input::ParseFieldError) -> Self {
Error::InvalidFieldValue(error)
}
}