use serde::Deserialize;
use serde_json::Value;
use textlane_core::Error;
const MAX_DEPTH: usize = 2048;
pub(crate) fn read_json(text: &str) -> Result<Value, Error> {
if measure_depth(text) > MAX_DEPTH {
return Err(Error::new(
"tree-too-deep",
format!("JSON nests at most {MAX_DEPTH} levels"),
));
}
let mut reader = serde_json::Deserializer::from_str(text);
reader.disable_recursion_limit();
let value = Value::deserialize(serde_stacker::Deserializer::new(&mut reader));
let value = value.and_then(|value| reader.end().map(|()| value));
value.map_err(|error| Error::new("invalid-json", error.to_string()))
}
fn measure_depth(text: &str) -> usize {
let (mut depth, mut deepest) = (0usize, 0usize);
let (mut quoted, mut escaped) = (false, false);
for byte in text.bytes() {
match (quoted, byte) {
(true, _) if escaped => escaped = false,
(true, b'\\') => escaped = true,
(true, b'"') | (false, b'"') => quoted = !quoted,
(false, b'[' | b'{') => {
depth += 1;
deepest = deepest.max(depth);
}
(false, b']' | b'}') => depth = depth.saturating_sub(1),
_ => {}
}
}
deepest
}
#[cfg(test)]
#[path = "read_unit.rs"]
mod unit;