use serde::de::DeserializeOwned;
#[derive(Debug, Clone)]
pub enum ParsedOrUnknown<T> {
Parsed(T),
Unknown(ObjCoords),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeType {
Object,
Array,
}
#[derive(Debug, Clone)]
pub struct ObjCoords {
pub start: usize,
pub end: usize, pub kind: NodeType,
pub children: Vec<ObjCoords>,
}
impl ObjCoords {
pub fn new(start: usize, end: usize, kind: NodeType, children: Vec<ObjCoords>) -> Self {
Self { start, end, kind, children }
}
}
#[derive(Debug)]
struct Frame {
start: usize,
kind: NodeType,
children: Vec<ObjCoords>,
}
pub fn find_json_structures(text: &str) -> Vec<ObjCoords> {
let bytes = text.as_bytes();
let mut results: Vec<ObjCoords> = Vec::new();
let mut stack: Vec<Frame> = Vec::new();
let mut in_string = false;
let mut escape = false;
for (i, &b) in bytes.iter().enumerate() {
if in_string {
if escape {
escape = false;
continue;
}
match b {
b'\\' => escape = true,
b'"' => in_string = false,
_ => {}
}
continue;
}
match b {
b'"' => in_string = true,
b'{' => stack.push(Frame { start: i, kind: NodeType::Object, children: Vec::new() }),
b'[' => stack.push(Frame { start: i, kind: NodeType::Array, children: Vec::new() }),
b'}' => {
if let Some(frame) = stack.pop() {
if frame.kind == NodeType::Object {
let node = ObjCoords::new(frame.start, i, NodeType::Object, frame.children);
if let Some(parent) = stack.last_mut() {
parent.children.push(node);
} else {
results.push(node);
}
}
}
}
b']' => {
if let Some(frame) = stack.pop() {
if frame.kind == NodeType::Array {
let node = ObjCoords::new(frame.start, i, NodeType::Array, frame.children);
if let Some(parent) = stack.last_mut() {
parent.children.push(node);
} else {
results.push(node);
}
}
}
}
_ => {}
}
}
results
}
#[derive(Debug, Default)]
pub struct JsonStreamParser {
stack: Vec<Frame>,
in_string: bool,
escape: bool,
offset: usize,
}
impl JsonStreamParser {
pub fn new() -> Self { Self::default() }
pub fn feed(&mut self, chunk: &str) -> Vec<ObjCoords> {
let bytes = chunk.as_bytes();
let mut roots: Vec<ObjCoords> = Vec::new();
for (i, &b) in bytes.iter().enumerate() {
let idx = self.offset + i;
if self.in_string {
if self.escape {
self.escape = false;
continue;
}
match b {
b'\\' => self.escape = true,
b'"' => self.in_string = false,
_ => {}
}
continue;
}
match b {
b'"' => self.in_string = true,
b'{' => self.stack.push(Frame { start: idx, kind: NodeType::Object, children: Vec::new() }),
b'[' => self.stack.push(Frame { start: idx, kind: NodeType::Array, children: Vec::new() }),
b'}' => {
if let Some(frame) = self.stack.pop() {
if frame.kind == NodeType::Object {
let node = ObjCoords::new(frame.start, idx, NodeType::Object, frame.children);
if let Some(parent) = self.stack.last_mut() {
parent.children.push(node);
} else {
roots.push(node);
}
}
}
}
b']' => {
if let Some(frame) = self.stack.pop() {
if frame.kind == NodeType::Array {
let node = ObjCoords::new(frame.start, idx, NodeType::Array, frame.children);
if let Some(parent) = self.stack.last_mut() {
parent.children.push(node);
} else {
roots.push(node);
}
}
}
}
_ => {}
}
}
self.offset += bytes.len();
roots
}
}
fn descend_deserialize<T: DeserializeOwned>(text: &str, node: &ObjCoords, out: &mut Vec<ParsedOrUnknown<T>>) {
let slice_end = node.end + 1; let candidate = &text[node.start..slice_end];
if let Ok(parsed) = serde_json::from_str::<T>(candidate) {
out.push(ParsedOrUnknown::Parsed(parsed));
return; }
let before_len = out.len();
for child in &node.children {
descend_deserialize::<T>(text, child, out);
}
if out.len() == before_len {
out.push(ParsedOrUnknown::Unknown(node.clone()));
}
}
pub fn deserialize_stream_map<T: DeserializeOwned>(text: &str) -> Vec<ParsedOrUnknown<T>> {
let mut out = Vec::new();
let roots = find_json_structures(text);
for node in &roots {
descend_deserialize::<T>(text, node, &mut out);
}
out
}