use crate::document::{Item, MatrixList};
use std::collections::BTreeMap;
#[derive(Debug)]
pub(super) enum Frame {
Root {
object: BTreeMap<String, Item>,
},
Object {
indent: usize,
key: String,
object: BTreeMap<String, Item>,
},
List {
row_indent: usize,
type_name: String,
schema: Vec<String>,
last_row_values: Option<Vec<crate::value::Value>>,
list: Vec<crate::document::Node>,
key: String,
count_hint: Option<usize>,
},
}
pub(super) fn pop_frames(stack: &mut Vec<Frame>, current_indent: usize) {
while stack.len() > 1 {
let should_pop = match stack.last().expect("stack has at least 2 elements") {
Frame::Root { .. } => false,
Frame::Object { indent, .. } => current_indent <= *indent,
Frame::List { row_indent, .. } => current_indent < *row_indent,
};
if should_pop {
let frame = stack.pop().expect("stack has at least 2 elements");
attach_frame_to_parent(stack, frame);
} else {
break;
}
}
}
pub(super) fn attach_frame_to_parent(stack: &mut [Frame], frame: Frame) {
match frame {
Frame::Object { key, object, .. } => {
let item = Item::Object(object);
insert_into_parent(stack, key, item);
}
Frame::List {
key,
type_name,
schema,
list,
count_hint,
..
} => {
let mut matrix_list = if let Some(count) = count_hint {
MatrixList::with_count_hint(type_name, schema, count)
} else {
MatrixList::new(type_name, schema)
};
matrix_list.rows = list;
insert_into_parent(stack, key, Item::List(matrix_list));
}
Frame::Root { .. } => {}
}
}
pub(super) fn insert_into_parent(stack: &mut [Frame], key: String, item: Item) {
if let Some(parent) = stack.last_mut() {
match parent {
Frame::Root { object } | Frame::Object { object, .. } => {
object.insert(key, item);
}
Frame::List { list, .. } => {
if let Some(parent_node) = list.last_mut() {
if let Item::List(child_list) = item {
let children = parent_node
.children
.get_or_insert_with(|| Box::new(BTreeMap::new()));
children
.entry(child_list.type_name.clone())
.or_default()
.extend(child_list.rows);
}
}
}
}
}
}