evobench_tools/serde_util/
json5_from_str.rs

1//! Try to provide location information for errors from the `json5`
2//! crate
3//!
4//! The latest json5, 0.4.1, includes location info including errors,
5//! but its `Display` implementation does not show the location; also
6//! it does not offer a method to retrieve the location, only pattern
7//! matching which they indicate will break with future versions.
8
9use std::fmt::Display;
10
11use serde::Deserialize;
12use serde_json5::Location;
13
14pub struct Json5FromStrLocation(pub Location);
15
16impl Display for Json5FromStrLocation {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        let Location { line, column } = &self.0;
19        write!(f, "{line}:{column}")
20    }
21}
22
23pub fn json5_error_location(e: &serde_json5::Error) -> Option<Json5FromStrLocation> {
24    match e {
25        serde_json5::Error::Message { msg: _, location } => location
26            .as_ref()
27            .map(|location| Json5FromStrLocation(location.clone())),
28    }
29}
30
31#[derive(Debug, thiserror::Error)]
32pub struct Json5FromStrError(pub serde_json5::Error);
33
34impl Json5FromStrError {
35    pub fn message_without_location(&self) -> &str {
36        match &self.0 {
37            serde_json5::Error::Message { msg, location: _ } => msg,
38        }
39    }
40
41    pub fn location(&self) -> Option<Json5FromStrLocation> {
42        json5_error_location(&self.0)
43    }
44}
45
46impl Display for Json5FromStrError {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        let msg = self.message_without_location();
49        if let Some(location) = self.location() {
50            write!(f, "{msg} at line:column {location}")
51        } else {
52            write!(f, "{msg}")
53        }
54    }
55}
56
57pub fn json5_from_str<'t, T: Deserialize<'t>>(s: &'t str) -> Result<T, Json5FromStrError> {
58    serde_json5::from_str(s).map_err(Json5FromStrError)
59}