crates/nornir-parquet-delta/src/error.rs
/// Everything that can go wrong mirroring a parquet file.
///
/// [`Error::Hole`] is the one that matters: it is the named failure that stands where a
/// sparse file would otherwise hand a reader a page of zeros and let it answer.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// **A read touched bytes the mirror does not hold.** Never a zero page, never a
/// silent wrong answer. `want` is the range the parquet reader asked for.
#[error(
"mirror hole: bytes {}..{} are not held (the mirror holds {held_chunks} of {total_chunks} chunks)",
want_offset,
want_offset + want_len
)]
Hole {
/// First byte the reader asked for.
want_offset: u64,
/// How many bytes it asked for.
want_len: u64,
/// Chunks the mirror holds right now.
held_chunks: u64,
/// Chunks the source has in total.
total_chunks: u64,
},
/// The mirror on disk was taken from a DIFFERENT version of the source. The whole
/// file is invalid — a parquet footer names byte offsets, and a re-written source
/// moves every one of them.
#[error("mirror is stale: it holds source version {held:?}, the source is now {expected:?}")]
StaleSource {
/// The token the mirror was created with.
held: String,
/// The token the caller says the source carries now.
expected: String,
},
/// The bytes handed to [`crate::Mirror::accept`] are not the length the footer says
/// that chunk is. Accepting them would put the file permanently out of phase.
#[error("chunk (row group {row_group}, column {column}) is {want} bytes, got {got}")]
WrongLength {
/// The row group the piece belongs to.
row_group: usize,
/// The leaf column index.
column: usize,
/// What the footer says.
want: u64,
/// What was offered.
got: u64,
},
/// A [`crate::Need`] named a row group or column the source does not have.
#[error("no such {what} {index} (the source has {count})")]
OutOfRange {
/// `"row group"` or `"column"`.
what: &'static str,
/// What was asked for.
index: usize,
/// What exists.
count: usize,
},
/// The bytes are not a parquet file (or not one this far).
#[error("not a parquet file: {why}")]
NotParquet {
/// What gave it away.
why: String,
},
/// The sidecar state file is not one of ours, or is from a future format.
#[error("mirror state file is unreadable: {why}")]
BadState {
/// What gave it away.
why: String,
},
/// Underlying I/O.
#[error("mirror i/o: {0}")]
Io(#[from] std::io::Error),
/// The footer would not parse.
#[error("footer: {0}")]
Parquet(#[from] parquet::errors::ParquetError),
}