use memchr::{memchr, memchr2};
use crate::error::Error;
use crate::value::Value;
use super::parser::Parser;
pub(crate) fn parse_str(text: &str) -> Result<Value, Error> {
let mut parser = Parser::new();
let bytes = text.as_bytes();
if memchr(b'\r', bytes).is_none() {
let mut line_start: usize = 0;
let mut line_num: usize = 0;
loop {
let end = memchr(b'\n', &bytes[line_start..])
.map(|p| line_start + p)
.unwrap_or(bytes.len());
line_num += 1;
let line: &str = &text[line_start..end];
parser.handle_line(line, line_num, line_start as u32)?;
if end == bytes.len() {
break;
}
line_start = end + 1;
}
return parser.finish(bytes.len() as u32);
}
let mut line_start: usize = 0;
let mut line_num: usize = 0;
while line_start <= bytes.len() {
if line_start == bytes.len() {
break;
}
let pos = memchr2(b'\n', b'\r', &bytes[line_start..])
.map(|p| line_start + p)
.unwrap_or(bytes.len());
let content_end = pos;
let next_start = if pos < bytes.len() {
if bytes[pos] == b'\r' {
if pos + 1 < bytes.len() && bytes[pos + 1] == b'\n' {
pos + 2
} else {
pos + 1
}
} else {
pos + 1
}
} else {
bytes.len() + 1
};
let line: &str = &text[line_start..content_end];
line_num += 1;
parser.handle_line(line, line_num, line_start as u32)?;
line_start = next_start;
}
parser.finish(bytes.len() as u32)
}