use std::{
fmt::{Display, Formatter},
result::Result,
};
pub trait LineInfoResult<T, E>: Sized {
fn simple(self) -> Result<T, WithLineInfo<E>>;
fn index(self, i: usize) -> Result<T, WithLineInfo<E>>;
fn line(self, i: usize, line: &[u8]) -> Result<T, WithLineInfo<E>>;
}
#[derive(Debug)]
pub enum WithLineInfo<T> {
None(T),
Index(usize, T),
Line(usize, String, T),
}
impl<T> Display for WithLineInfo<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter) -> std::result::Result<(), std::fmt::Error> {
match self {
Self::None(x) => write!(f, "{}", x),
Self::Index(i, x) => write!(f, "Line #{}: '{}'", i, x),
Self::Line(i, l, x) => write!(f, "Line #{}: '{}' '{}'", i, x, l),
}
}
}
pub type IOResult<T, E> = Result<T, WithLineInfo<E>>;
impl<T, E> LineInfoResult<T, E> for Result<T, E> {
fn simple(self) -> Result<T, WithLineInfo<E>> {
self.map_err(|e| WithLineInfo::None(e))
}
fn index(self, i: usize) -> Result<T, WithLineInfo<E>> {
self.map_err(|e| WithLineInfo::Index(i, e))
}
fn line(self, i: usize, line: &[u8]) -> Result<T, WithLineInfo<E>> {
self.map_err(|e| WithLineInfo::Line(i, String::from_utf8_lossy(line).to_string(), e))
}
}