use crate::{
brackets::{brackets_map, is_closing_bracket, is_opening_bracket, BracketStack},
json_object::JSONLString,
};
pub struct LineProcessor {
pub bracket_stack: BracketStack,
pub jsonl_string: JSONLString,
}
impl LineProcessor {
pub fn new() -> Self {
Self {
bracket_stack: BracketStack::new(),
jsonl_string: JSONLString::new(),
}
}
pub fn push_bracket(&mut self, byte: &char) {
self.bracket_stack.push(&byte);
}
pub fn process_line(&mut self, line: &str) {
let line = line.trim();
let start_char = line.chars().next().unwrap();
let end_char = self.get_end_char(&line);
if is_opening_bracket(&start_char) {
self.push_bracket(&start_char);
}
if is_closing_bracket(&end_char) {
self.bracket_stack.pop_pair(&end_char);
}
if is_opening_bracket(&end_char) {
self.push_bracket(&end_char);
}
if is_closing_bracket(&start_char) {
self.bracket_stack.pop_pair(&start_char);
}
self.jsonl_string.push_str(&line);
if self.should_print() {
println!("{}", self.jsonl_string);
self.jsonl_string.clear();
}
}
fn get_end_char(&self, line: &str) -> char {
let cleaned_line = line.trim_end_matches(',');
if cleaned_line.len() == 1 {
return ' ';
}
let last_char = cleaned_line.chars().last().unwrap();
if is_closing_bracket(&last_char) {
let second_to_last_char = cleaned_line.chars().rev().nth(1).unwrap();
if brackets_map().get(&last_char) == Some(&second_to_last_char) {
return ' '; }
}
last_char
}
fn should_print(&mut self) -> bool {
self.bracket_stack.len() == 1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_returns_processor_with_empty_attrs() {
let processor = LineProcessor::new();
assert_eq!(processor.bracket_stack.len(), 0);
assert_eq!(processor.jsonl_string.len(), 0);
}
#[test]
fn test_get_end_char_returns_empty_char_when_line_is_one_char() {
let processor = LineProcessor::new();
let line = "{";
assert_eq!(processor.get_end_char(&line), ' ');
}
#[test]
fn test_get_end_char_returns_second_to_last_char_if_ends_with_comma() {
let processor = LineProcessor::new();
let line = " \"name\": \"John\",";
assert_eq!(processor.get_end_char(&line), '"');
}
#[test]
fn test_get_end_char_returns_last_char_if_does_not_end_with_comma() {
let processor = LineProcessor::new();
let line = " \"name\": \"John\"";
assert_eq!(processor.get_end_char(&line), '"');
}
#[test]
fn test_get_end_char_returns_empty_str_if_len_2_and_last_char_is_comma() {
let processor = LineProcessor::new();
let line = "{,";
assert_eq!(processor.get_end_char(&line), ' ');
}
#[test]
fn test_get_end_char_returns_str_if_last_two_open_and_close() {
let processor = LineProcessor::new();
let line = "cars: [],";
assert_eq!(processor.get_end_char(&line), ' ');
}
#[test]
fn test_process_line_returns_object_when_filled() {
let mut processor = LineProcessor::new();
processor.process_line("[");
assert_eq!(processor.bracket_stack.stack, vec!['[']);
processor.process_line(" {");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{']);
processor.process_line(" \"name\": \"John\",");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{']);
processor.process_line(" \"age\": 30,");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{']);
processor.process_line(" \"cars\": [");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[']);
processor.process_line(" \"cars\": [");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[', '[']);
processor.process_line(
" { \"name\": \"Ford\", \"models\": [ \"Fiesta\", \"Focus\", \"Mustang\" ] },",
);
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[', '[']);
processor
.process_line(" { \"name\": \"BMW\", \"models\": [ \"320\", \"X3\", \"X5\" ] },");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[', '[']);
processor.process_line(" { \"name\": \"Fiat\", \"models\": [ \"500\", \"Panda\" ] }");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[', '[']);
processor.process_line(" ]");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{', '[']);
processor.process_line(" ]");
assert_eq!(processor.should_print(), false);
assert_eq!(processor.bracket_stack.stack, vec!['[', '{']);
processor.process_line("}");
assert_eq!(processor.should_print(), true);
assert_eq!(processor.bracket_stack.stack, vec!['[']);
}
}