use std::process; use ron::error::Position; pub fn report_serde_json_err(src: &str, err: serde_json::Error) -> ! { report_serde_err(src, err.line(), err.column(), err.to_string()) } pub fn report_serde_ron_err(src: &str, err: ron::error::SpannedError) -> ! { let Position { line, col } = err.position; report_serde_err(src, line, col, err.to_string()) } pub fn report_serde_err(src: &str, line: usize, col: usize, msg: String) -> ! { use ariadne::{Label, Report, Source}; let offset = try_reconstruct_loc(src, line, col); Report::build(ariadne::ReportKind::Error, "test", offset) .with_label(Label::new(("test", offset..offset)).with_message("Something went wrong here!")) .with_message(msg) .with_note("We'd like to give better errors, but serde errors are horrible to work with...") .finish() .print(("test", Source::from(src))) .unwrap(); process::exit(1); } fn try_reconstruct_loc(src: &str, line_nr: usize, col_nr: usize) -> usize { let (line_nr, col_nr) = (line_nr - 1, col_nr - 1); src.lines() .enumerate() .fold(0, |acc, (i, line)| match i.cmp(&line_nr) { std::cmp::Ordering::Less => acc + line.len() + 1, std::cmp::Ordering::Equal => acc + col_nr, std::cmp::Ordering::Greater => acc, }) }