use anyhow::Context; use serde::{Deserialize, Serialize}; pub fn from_str Deserialize<'de>>(s: &str) -> anyhow::Result { serde_json::from_str(s).map_err(|e| anyhow::format_err!("{e}:\n{}", extract_context(&e, s))) } pub fn to_string(data: &S) -> anyhow::Result { serde_json::to_string(data).context("Could not serialize data to json") } pub fn to_string_pretty(data: &S) -> anyhow::Result { serde_json::to_string_pretty(data).context("Could not serialize data to json") } pub fn to_vec(data: &S) -> anyhow::Result> { serde_json::to_vec(data).context("Could not serialize data to json") } pub fn to_vec_pretty(data: &S) -> anyhow::Result> { serde_json::to_vec_pretty(data).context("Could not serialize data to json") } pub fn string(v: &str) -> String { serde_json::to_string(v).expect("Could not encode json string") } fn extract_context(serde_error: &serde_json::Error, s: &str) -> String { let lines: Vec<_> = s.lines().collect(); if lines.len() == 1 { let (col_begin, highlight) = if serde_error.column() > 30 { (serde_error.column() - 30, 30) } else { (1, serde_error.column()) }; let col_end = if lines[0].len() + 31 < serde_error.column() { lines[0].len() + 1 } else { serde_error.column() + 30 }; let mut line: String = lines[0] .chars() .skip(col_begin - 1) .take(col_end - col_begin) .collect(); line.push('\n'); line.extend(std::iter::repeat_n(' ', highlight - 1)); line.push('^'); line } else { let error_line = serde_error.line(); let mut result = String::new(); if error_line > 1 { result.push_str(&format!("{}: {}\n", error_line - 1, lines[error_line - 2])); } result.push_str(&format!("{}: {}\n", error_line, lines[error_line - 1])); result.push_str(&format!( "{} {}\n", " ".repeat(error_line.to_string().len()), std::iter::repeat_n(' ', serde_error.column() - 1) .chain(['^'].into_iter()) .collect::(), )); if lines.len() > error_line { result.push_str(&format!("{}: {}\n", error_line + 1, lines[error_line])); } result } }