use crate::{
error,
path::{Element, Path},
};
use std::{
collections::{vec_deque::Drain, VecDeque},
str::from_utf8,
};
#[derive(Debug, PartialEq)]
pub enum Output {
Start(usize),
End(usize),
Separator(usize),
Pending,
}
impl Output {
pub fn is_end(&self) -> bool {
match self {
Self::End(_) => true,
_ => false,
}
}
}
#[derive(Debug)]
enum ObjectKeyState {
Init,
Parse(StringState),
}
#[derive(Debug, PartialEq)]
enum StringState {
Normal,
Escaped,
}
#[derive(Debug)]
enum States {
Value(Option<Element>),
Str(StringState),
Number,
Bool,
Null,
Array(usize),
Object,
ObjectKey(ObjectKeyState),
Colon,
RemoveWhitespaces,
}
#[derive(Debug)]
pub struct Streamer {
path: Path,
states: Vec<States>,
pending: VecDeque<u8>,
pending_idx: usize,
total_idx: usize,
pop_path: bool,
}
impl Default for Streamer {
fn default() -> Self {
Self {
path: Path::default(),
states: vec![States::Value(None), States::RemoveWhitespaces],
pending: VecDeque::new(),
pending_idx: 0,
total_idx: 0,
pop_path: false,
}
}
}
impl Streamer {
pub fn new() -> Self {
Self::default()
}
pub fn current_path(&mut self) -> &mut Path {
&mut self.path
}
fn peek(&mut self) -> Option<u8> {
if self.pending.len() > self.pending_idx {
Some(self.pending[self.pending_idx])
} else {
None
}
}
fn forward(&mut self) {
if self.peek().is_some() {
self.pending_idx += 1;
}
}
fn advance(&mut self) -> Drain<u8> {
let to_remove = self.pending_idx;
if self.pending_idx > 0 {
self.total_idx += self.pending_idx;
self.pending_idx = 0;
}
self.pending.drain(0..to_remove)
}
pub fn feed(&mut self, input: &[u8]) {
self.pending.extend(input);
}
fn process_remove_whitespace(&mut self) -> Result<Option<Output>, error::General> {
while let Some(byte) = self.peek() {
if !byte.is_ascii_whitespace() {
self.advance();
return Ok(None);
}
self.forward();
}
self.states.push(States::RemoveWhitespaces);
Ok(Some(Output::Pending))
}
fn process_value(
&mut self,
element: Option<Element>,
) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
match byte {
b'"' => {
self.states.push(States::Str(StringState::Normal));
self.advance();
self.forward();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b'0'..=b'9' => {
self.states.push(States::Number);
self.advance();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b't' | b'f' => {
self.states.push(States::Bool);
self.advance();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b'n' => {
self.states.push(States::Null);
self.advance();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b'[' => {
self.states.push(States::Array(0));
self.states.push(States::RemoveWhitespaces);
self.states.push(States::Value(Some(Element::Index(0))));
self.states.push(States::RemoveWhitespaces);
self.advance();
self.forward();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b'{' => {
self.states.push(States::Object);
self.states.push(States::RemoveWhitespaces);
self.states.push(States::ObjectKey(ObjectKeyState::Init));
self.states.push(States::RemoveWhitespaces);
self.advance();
self.forward();
if let Some(element) = element {
self.path.push(element);
}
Ok(Some(Output::Start(self.total_idx)))
}
b']' | b'}' => {
Ok(None)
}
byte => {
Err(error::IncorrectInput::new(byte, self.total_idx + self.pending_idx).into())
}
}
} else {
self.states.push(States::Value(element));
Ok(Some(Output::Pending))
}
}
fn process_str(&mut self, state: StringState) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
match byte {
b'"' => {
if state == StringState::Normal {
self.forward();
self.advance();
Ok(Some(Output::End(self.total_idx)))
} else {
self.forward();
self.states.push(States::Str(StringState::Normal));
Ok(None)
}
}
b'\\' => {
self.forward();
let new_state = match state {
StringState::Escaped => StringState::Normal,
StringState::Normal => StringState::Escaped,
};
self.states.push(States::Str(new_state));
Ok(None)
}
_ => {
self.forward();
self.states.push(States::Str(StringState::Normal));
Ok(None)
}
}
} else {
self.states.push(States::Str(state));
Ok(Some(Output::Pending))
}
}
fn process_number(&mut self) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
if byte.is_ascii_digit() || byte == b'.' {
self.forward();
self.states.push(States::Number);
Ok(None)
} else {
self.advance();
Ok(Some(Output::End(self.total_idx)))
}
} else {
self.states.push(States::Number);
Ok(Some(Output::Pending))
}
}
fn process_bool(&mut self) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
if byte.is_ascii_alphabetic() {
self.forward();
self.states.push(States::Bool);
Ok(None)
} else {
self.advance();
Ok(Some(Output::End(self.total_idx)))
}
} else {
self.states.push(States::Bool);
Ok(Some(Output::Pending))
}
}
fn process_null(&mut self) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
if byte.is_ascii_alphabetic() {
self.forward();
self.states.push(States::Null);
Ok(None)
} else {
self.advance();
Ok(Some(Output::End(self.total_idx)))
}
} else {
self.states.push(States::Null);
Ok(Some(Output::Pending))
}
}
fn process_array(&mut self, idx: usize) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
match byte {
b']' => {
self.forward();
self.advance();
Ok(Some(Output::End(self.total_idx)))
}
b',' => {
self.forward();
self.states.push(States::Array(idx + 1));
self.states.push(States::RemoveWhitespaces);
self.states
.push(States::Value(Some(Element::Index(idx + 1))));
self.states.push(States::RemoveWhitespaces);
Ok(Some(Output::Separator(self.total_idx)))
}
byte => {
Err(error::IncorrectInput::new(byte, self.total_idx + self.pending_idx).into())
}
}
} else {
self.states.push(States::Array(idx));
Ok(Some(Output::Pending))
}
}
fn process_object(&mut self) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
match byte {
b'}' => {
self.forward();
self.advance();
Ok(Some(Output::End(self.total_idx)))
}
b',' => {
self.forward();
self.states.push(States::Object);
self.states.push(States::RemoveWhitespaces);
self.states.push(States::ObjectKey(ObjectKeyState::Init));
self.states.push(States::RemoveWhitespaces);
Ok(Some(Output::Separator(self.total_idx)))
}
byte => {
Err(error::IncorrectInput::new(byte, self.total_idx + self.pending_idx).into())
}
}
} else {
self.states.push(States::Object);
Ok(Some(Output::Pending))
}
}
fn process_object_key(
&mut self,
state: ObjectKeyState,
) -> Result<Option<Output>, error::General> {
match state {
ObjectKeyState::Init => {
if let Some(byte) = self.peek() {
match byte {
b'"' => {
self.advance();
self.forward();
self.states.push(States::ObjectKey(ObjectKeyState::Parse(
StringState::Normal,
)));
Ok(None)
}
b'}' => Ok(None),
byte => Err(error::IncorrectInput::new(
byte,
self.total_idx + self.pending_idx,
)
.into()),
}
} else {
self.states.push(States::ObjectKey(state));
Ok(Some(Output::Pending))
}
}
ObjectKeyState::Parse(string_state) => {
if let Some(byte) = self.peek() {
self.forward();
match string_state {
StringState::Normal => match byte {
b'\"' => {
let idx = self.pending_idx;
let slice = &self.advance().collect::<Vec<u8>>()[1..idx - 1];
let key = from_utf8(slice)?.to_string();
self.states.push(States::Value(Some(Element::Key(key))));
self.states.push(States::RemoveWhitespaces);
self.states.push(States::Colon);
self.states.push(States::RemoveWhitespaces);
Ok(None)
}
b'\\' => {
self.states.push(States::ObjectKey(ObjectKeyState::Parse(
StringState::Escaped,
)));
Ok(None)
}
_ => {
self.states.push(States::ObjectKey(ObjectKeyState::Parse(
StringState::Normal,
)));
Ok(None)
}
},
StringState::Escaped => {
self.states.push(States::ObjectKey(ObjectKeyState::Parse(
StringState::Normal,
)));
Ok(None)
}
}
} else {
self.states
.push(States::ObjectKey(ObjectKeyState::Parse(string_state)));
Ok(Some(Output::Pending))
}
}
}
}
fn process_colon(&mut self) -> Result<Option<Output>, error::General> {
if let Some(byte) = self.peek() {
if byte != b':' {
return Err(
error::IncorrectInput::new(byte, self.total_idx + self.pending_idx).into(),
);
}
self.forward();
Ok(None)
} else {
self.states.push(States::Colon);
Ok(Some(Output::Pending))
}
}
pub fn read(&mut self) -> Result<Output, error::General> {
loop {
while let Some(state) = self.states.pop() {
if self.pop_path {
self.path.pop();
self.pop_path = false;
}
match state {
States::RemoveWhitespaces => {
if let Some(output) = self.process_remove_whitespace()? {
return Ok(output);
}
}
States::Value(element) => {
if let Some(output) = self.process_value(element)? {
return Ok(output);
}
}
States::Str(state) => {
if let Some(output) = self.process_str(state)? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::Number => {
if let Some(output) = self.process_number()? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::Bool => {
if let Some(output) = self.process_bool()? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::Null => {
if let Some(output) = self.process_null()? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::Array(idx) => {
if let Some(output) = self.process_array(idx)? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::Object => {
if let Some(output) = self.process_object()? {
self.pop_path = output.is_end();
return Ok(output);
}
}
States::ObjectKey(state) => {
if let Some(output) = self.process_object_key(state)? {
return Ok(output);
}
}
States::Colon => {
if let Some(output) = self.process_colon()? {
return Ok(output);
}
}
}
}
self.states.push(States::Value(None));
self.states.push(States::RemoveWhitespaces);
}
}
}
#[cfg(test)]
mod test {
use super::{Output, Streamer};
use crate::path::Path;
use std::convert::TryFrom;
fn make_path(path: &str) -> Path {
Path::try_from(path).unwrap()
}
#[test]
fn test_spaces() {
let mut streamer = Streamer::new();
streamer.feed(br#" "#);
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_string() {
let mut streamer = Streamer::new();
streamer.feed(br#" "test string \" \\\" [ ] {} , :\\""#);
assert_eq!(streamer.read().unwrap(), Output::Start(2));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(36));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
let mut streamer = Streamer::new();
streamer.feed(br#"" another one " "#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(15));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_number() {
let mut streamer = Streamer::new();
streamer.feed(br#" 3.24 "#);
assert_eq!(streamer.read().unwrap(), Output::Start(1));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(5));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_bool() {
let mut streamer = Streamer::new();
streamer.feed(br#" true "#);
assert_eq!(streamer.read().unwrap(), Output::Start(2));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(6));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_null() {
let mut streamer = Streamer::new();
streamer.feed(br#"null"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
let mut streamer = Streamer::new();
streamer.feed(br#"null "#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(4));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_array() {
let mut streamer = Streamer::new();
streamer.feed(br#"[ null, 33, "string" ]"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(2));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::End(6));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(6));
assert_eq!(streamer.read().unwrap(), Output::Start(8));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::End(10));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(10));
assert_eq!(streamer.read().unwrap(), Output::Start(12));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::End(20));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::End(22));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_array_pending() {
let mut streamer = Streamer::new();
streamer.feed(br#"[ null, 3"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(2));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::End(6));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(6));
assert_eq!(streamer.read().unwrap(), Output::Start(8));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::Pending);
assert_eq!(streamer.current_path(), &make_path("[1]"));
streamer.feed(br#"3,"#);
assert_eq!(streamer.read().unwrap(), Output::End(10));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(10));
assert_eq!(streamer.read().unwrap(), Output::Pending);
assert_eq!(streamer.current_path(), &make_path(""));
streamer.feed(br#" "string" ]"#);
assert_eq!(streamer.read().unwrap(), Output::Start(12));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::End(20));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::End(22));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_empty_array() {
let mut streamer = Streamer::new();
streamer.feed(br#"[]"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(2));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_array_in_array() {
let mut streamer = Streamer::new();
streamer.feed(br#"[ [], 33, ["string" , 44], [ ]]"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(2));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::End(4));
assert_eq!(streamer.current_path(), &make_path("[0]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(4));
assert_eq!(streamer.read().unwrap(), Output::Start(6));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::End(8));
assert_eq!(streamer.current_path(), &make_path("[1]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(8));
assert_eq!(streamer.read().unwrap(), Output::Start(10));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::Start(11));
assert_eq!(streamer.current_path(), &make_path("[2][0]"));
assert_eq!(streamer.read().unwrap(), Output::End(19));
assert_eq!(streamer.current_path(), &make_path("[2][0]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(20));
assert_eq!(streamer.read().unwrap(), Output::Start(22));
assert_eq!(streamer.current_path(), &make_path("[2][1]"));
assert_eq!(streamer.read().unwrap(), Output::End(24));
assert_eq!(streamer.current_path(), &make_path("[2][1]"));
assert_eq!(streamer.read().unwrap(), Output::End(25));
assert_eq!(streamer.current_path(), &make_path("[2]"));
assert_eq!(streamer.read().unwrap(), Output::Separator(25));
assert_eq!(streamer.read().unwrap(), Output::Start(27));
assert_eq!(streamer.current_path(), &make_path("[3]"));
assert_eq!(streamer.read().unwrap(), Output::End(31));
assert_eq!(streamer.current_path(), &make_path("[3]"));
assert_eq!(streamer.read().unwrap(), Output::End(32));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_object() {
let mut streamer = Streamer::new();
streamer.feed(br#"{"a":"a", "b" : true , "c": null, " \" \\\" \\": 33}"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(5));
assert_eq!(streamer.current_path(), &make_path("{\"a\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(8));
assert_eq!(streamer.current_path(), &make_path("{\"a\"}"));
assert_eq!(streamer.read().unwrap(), Output::Separator(8));
assert_eq!(streamer.read().unwrap(), Output::Start(17));
assert_eq!(streamer.current_path(), &make_path("{\"b\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(21));
assert_eq!(streamer.current_path(), &make_path("{\"b\"}"));
assert_eq!(streamer.read().unwrap(), Output::Separator(22));
assert_eq!(streamer.read().unwrap(), Output::Start(29));
assert_eq!(streamer.current_path(), &make_path("{\"c\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(33));
assert_eq!(streamer.current_path(), &make_path("{\"c\"}"));
assert_eq!(streamer.read().unwrap(), Output::Separator(33));
assert_eq!(streamer.read().unwrap(), Output::Start(50));
assert_eq!(streamer.current_path(), &make_path(r#"{" \" \\\" \\"}"#));
assert_eq!(streamer.read().unwrap(), Output::End(52));
assert_eq!(streamer.current_path(), &make_path(r#"{" \" \\\" \\"}"#));
assert_eq!(streamer.read().unwrap(), Output::End(53));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_empty_object() {
let mut streamer = Streamer::new();
streamer.feed(br#"{}"#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(2));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_object_in_object() {
let mut streamer = Streamer::new();
streamer.feed(br#" {"u": {}, "j": {"x": { }, "y": 10}} "#);
assert_eq!(streamer.read().unwrap(), Output::Start(1));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(7));
assert_eq!(streamer.current_path(), &make_path("{\"u\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(9));
assert_eq!(streamer.current_path(), &make_path("{\"u\"}"));
assert_eq!(streamer.read().unwrap(), Output::Separator(9));
assert_eq!(streamer.read().unwrap(), Output::Start(16));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}"));
assert_eq!(streamer.read().unwrap(), Output::Start(22));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}{\"x\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(26));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}{\"x\"}"));
assert_eq!(streamer.read().unwrap(), Output::Separator(26));
assert_eq!(streamer.read().unwrap(), Output::Start(33));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}{\"y\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(35));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}{\"y\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(36));
assert_eq!(streamer.current_path(), &make_path("{\"j\"}"));
assert_eq!(streamer.read().unwrap(), Output::End(37));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
#[test]
fn test_complex_with_pending() {
const COMPLEX_DATA: &[u8] = br#" [{"aha y": {}, "j": {"x": [{ }, [ {}, null ]], "y" : 10}}, null, 43, [ {"a": false} ] ]"#;
for i in 0..COMPLEX_DATA.len() {
let start_data = &COMPLEX_DATA[0..i];
let end_data = &COMPLEX_DATA[i..];
let mut streamer = Streamer::new();
streamer.feed(start_data);
let mut terminate = false;
let mut get_item = |path: Option<&str>| loop {
match streamer.read() {
Ok(Output::Pending) => {
if terminate {
break Output::Pending;
} else {
terminate = true;
streamer.feed(end_data);
}
continue;
}
Ok(e) => {
if let Some(pth) = path {
assert_eq!(streamer.current_path(), &make_path(pth));
}
return e;
}
Err(_) => panic!("Error occured"),
}
};
assert_eq!(get_item(Some("")), Output::Start(1));
assert_eq!(get_item(Some("[0]")), Output::Start(2));
assert_eq!(get_item(Some("[0]{\"aha y\"}")), Output::Start(12));
assert_eq!(get_item(Some("[0]{\"aha y\"}")), Output::End(14));
assert_eq!(get_item(None), Output::Separator(14));
assert_eq!(get_item(Some("[0]{\"j\"}")), Output::Start(21));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}")), Output::Start(27));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[0]")), Output::Start(28));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[0]")), Output::End(32));
assert_eq!(get_item(None), Output::Separator(32));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1]")), Output::Start(34));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1][0]")), Output::Start(36));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1][0]")), Output::End(38));
assert_eq!(get_item(None), Output::Separator(38));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1][1]")), Output::Start(40));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1][1]")), Output::End(44));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}[1]")), Output::End(46));
assert_eq!(get_item(Some("[0]{\"j\"}{\"x\"}")), Output::End(47));
assert_eq!(get_item(None), Output::Separator(47));
assert_eq!(get_item(Some("[0]{\"j\"}{\"y\"}")), Output::Start(55));
assert_eq!(get_item(Some("[0]{\"j\"}{\"y\"}")), Output::End(57));
assert_eq!(get_item(Some("[0]{\"j\"}")), Output::End(58));
assert_eq!(get_item(Some("[0]")), Output::End(59));
assert_eq!(get_item(None), Output::Separator(59));
assert_eq!(get_item(Some("[1]")), Output::Start(61));
assert_eq!(get_item(Some("[1]")), Output::End(65));
assert_eq!(get_item(None), Output::Separator(65));
assert_eq!(get_item(Some("[2]")), Output::Start(67));
assert_eq!(get_item(Some("[2]")), Output::End(69));
assert_eq!(get_item(None), Output::Separator(69));
assert_eq!(get_item(Some("[3]")), Output::Start(71));
assert_eq!(get_item(Some("[3][0]")), Output::Start(73));
assert_eq!(get_item(Some("[3][0]{\"a\"}")), Output::Start(79));
assert_eq!(get_item(Some("[3][0]{\"a\"}")), Output::End(84));
assert_eq!(get_item(Some("[3][0]")), Output::End(85));
assert_eq!(get_item(Some("[3]")), Output::End(87));
assert_eq!(get_item(Some("")), Output::End(89));
assert_eq!(get_item(None), Output::Pending);
}
}
#[test]
fn test_utf8() {
let utf8_data: Vec<u8> = r#"[{"š𐍈€": "€š𐍈"}, "𐍈€š"]"#.to_string().into_bytes();
for i in 0..utf8_data.len() {
let start_data = &utf8_data[0..i];
let end_data = &utf8_data[i..];
let mut streamer = Streamer::new();
streamer.feed(start_data);
let mut terminate = false;
let mut get_item = |path: Option<&str>| loop {
match streamer.read() {
Ok(Output::Pending) => {
if terminate {
break Output::Pending;
} else {
terminate = true;
streamer.feed(end_data);
}
continue;
}
Ok(e) => {
if let Some(pth) = path {
assert_eq!(streamer.current_path(), &make_path(pth));
}
return e;
}
Err(_) => panic!("Error occured"),
}
};
assert_eq!(get_item(Some("")), Output::Start(0));
assert_eq!(get_item(Some("[0]")), Output::Start(1));
assert_eq!(get_item(Some("[0]{\"š𐍈€\"}")), Output::Start(15));
assert_eq!(get_item(Some("[0]{\"š𐍈€\"}")), Output::End(26));
assert_eq!(get_item(Some("[0]")), Output::End(27));
assert_eq!(get_item(None), Output::Separator(27));
assert_eq!(get_item(Some("[1]")), Output::Start(29));
assert_eq!(get_item(Some("[1]")), Output::End(40));
assert_eq!(get_item(Some("")), Output::End(41));
assert_eq!(get_item(None), Output::Pending);
}
}
#[test]
fn test_multiple_input_flat() {
let mut streamer = Streamer::new();
streamer.feed(br#""first" "second""third""#);
assert_eq!(streamer.read().unwrap(), Output::Start(0));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(7));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(8));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(16));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Start(16));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::End(23));
assert_eq!(streamer.current_path(), &make_path(""));
assert_eq!(streamer.read().unwrap(), Output::Pending);
}
}