use thiserror::Error;
use uuid::Uuid;
#[derive(Error, Debug)]
pub enum PipeError {
#[error("Writer already acquired for pipe '{pipe_name}' - only one writer allowed")]
WriterAlreadyAcquired { pipe_name: String },
#[error("Reader {reader_id} not registered with pipe '{pipe_name}'")]
ReaderNotRegistered { reader_id: Uuid, pipe_name: String },
#[error("Reader {reader_id} not registered with read-only pipe")]
ReadOnlyReaderNotRegistered { reader_id: Uuid },
#[error("Buffer capacity exceeded on pipe '{pipe_name}': trying to write {requested} elements into buffer capable of holding {capacity}")]
WriteCapacityExceeded {
pipe_name: String,
requested: usize,
capacity: usize,
},
#[error("Buffer capacity exceeded on pipe '{pipe_name}': trying to read {requested} elements into buffer capable of holding {capacity}")]
ReadCapacityExceeded {
pipe_name: String,
requested: usize,
capacity: usize,
},
#[error("{context}: not enough data. Requested {requested} elements from position {position}, but only {available} elements total")]
InsufficientData {
context: String,
requested: usize,
position: usize,
available: usize,
},
#[error("Array bounds error: trying to access indices {start_idx}..{end_idx} in slice of length {slice_len}")]
ArrayBoundsError {
start_idx: usize,
end_idx: usize,
slice_len: usize,
},
#[error(
"Buffer size {buffer_size} is not divisible by type size {type_size} for type {type_name}"
)]
TypeSizeMismatch {
buffer_size: usize,
type_size: usize,
type_name: String,
},
#[error("Writer dropped on pipe '{pipe_name}' and there isn't enough data to meet the request of {requested} elements")]
WriterDroppedInsufficientData { pipe_name: String, requested: usize },
#[error("Writer dropped on pipe '{pipe_name}'. Pipe shouldn't be written to any more")]
WriterDroppedStillWriting { pipe_name: String },
#[error("Not enough data remaining")]
NotEnoughDataRemaining,
#[error("Memory mapping error")]
MemoryMappingError(#[from] nix::Error),
#[error("I/O error")]
IoError(#[from] std::io::Error),
#[error("Array shape error")]
ArrayShapeError(#[from] ndarray::ShapeError),
#[error("String conversion error")]
StringConversionError(#[from] std::ffi::NulError),
#[error("Integer conversion error")]
IntegerConversionError(#[from] std::num::TryFromIntError),
#[error("Other error: {message}")]
Other { message: String },
}
pub type Result<T> = std::result::Result<T, PipeError>;
impl PipeError {
pub fn insufficient_data(
context: impl Into<String>,
requested: usize,
position: usize,
available: usize,
) -> Self {
Self::InsufficientData {
context: context.into(),
requested,
position,
available,
}
}
pub fn array_bounds_error(start_idx: usize, end_idx: usize, slice_len: usize) -> Self {
Self::ArrayBoundsError {
start_idx,
end_idx,
slice_len,
}
}
pub fn type_size_mismatch(
buffer_size: usize,
type_size: usize,
type_name: impl Into<String>,
) -> Self {
Self::TypeSizeMismatch {
buffer_size,
type_size,
type_name: type_name.into(),
}
}
pub fn is_end_of_stream(&self) -> bool {
matches!(
self,
PipeError::WriterDroppedInsufficientData { .. } | PipeError::NotEnoughDataRemaining
)
}
pub fn is_insufficient_data(&self) -> bool {
matches!(
self,
PipeError::InsufficientData { .. }
| PipeError::WriterDroppedInsufficientData { .. }
| PipeError::NotEnoughDataRemaining
)
}
}