use super::SyntaxErr;
const WHITESPACES: &[u8] = &[b'\t', b'\n', b'\r', b' '];
#[inline]
pub fn skip_whitespaces(json: &[u8], idx: &mut usize) {
while json.len() > *idx {
if WHITESPACES.contains(&json[*idx]) {
*idx += 1;
continue;
}
return;
}
}
#[inline]
pub fn get_until_or_unexpected_end<'a>(
json: &'a [u8],
idx: &mut usize,
stoppers: &[u8],
) -> Result<&'a [u8], SyntaxErr> {
let start = *idx;
while json.len() > *idx {
if stoppers.contains(&json[*idx]) {
return Ok(&json[start..*idx]);
};
*idx += 1;
}
Err(SyntaxErr::unexpected_end(idx))
}
#[inline]
pub fn get_or_unexpected_end(json: &[u8], idx: &mut usize) -> Result<u8, SyntaxErr> {
if json.len() > *idx {
return Ok(json[*idx]);
};
Err(SyntaxErr::unexpected_end(idx))
}
#[inline]
pub fn expect_and_skip(exp: u8, json: &[u8], idx: &mut usize) -> Result<(), SyntaxErr> {
match json.get(*idx) {
Some(b) => {
if *b != exp {
Err(SyntaxErr::unexpected_token(
unsafe { ::core::str::from_utf8_unchecked(&[exp]) },
&[*b],
idx,
))
} else {
*idx += 1;
Ok(())
}
}
None => Err(SyntaxErr::unexpected_end(idx)),
}
}
#[inline]
pub fn skip_value(json: &[u8], idx: &mut usize) -> Result<(), SyntaxErr> {
let byte = get_or_unexpected_end(json, idx)?;
match byte {
b'"' => skip_string(json, idx),
b'{' => skip_object(json, idx),
b'[' => skip_array(json, idx),
b'0'..=b'9' => {
skip_number(json, idx);
Ok(())
}
b'n' => skip_null(json, idx, "null"),
b't' => skip_true(json, idx, "true"),
b'f' => skip_false(json, idx, "false"),
_ => Err(SyntaxErr::unexpected_token(
"['\"', '{', '[', '0..9']",
&[byte],
idx,
)),
}
}
#[inline]
pub fn skip_string(json: &[u8], idx: &mut usize) -> Result<(), SyntaxErr> {
*idx += 1;
while json.len() > *idx {
match json[*idx] {
b'\\' => {
*idx += 2;
continue;
}
b'"' => {
*idx += 1;
return Ok(());
}
_ => *idx += 1,
}
}
Err(SyntaxErr::unexpected_end(idx))
}
#[inline]
pub fn skip_true(json: &[u8], idx: &mut usize, exp: &'static str) -> Result<(), SyntaxErr> {
if json.len() < *idx + 4 {
return Err(SyntaxErr::unexpected_end(&mut (json.len() + 1)));
};
if json[*idx + 1..=*idx + 3].eq("rue".as_bytes()) {
if json.len() < *idx + 5 {
*idx += 4;
return Ok(());
};
match json[*idx + 4] {
b',' | b' ' | b'}' | b']' | b'\n' | b'\r' | b'\t' => {
*idx += 4;
return Ok(());
}
_ => {
return Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx));
}
};
};
Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx))
}
#[inline]
pub fn skip_false(json: &[u8], idx: &mut usize, exp: &'static str) -> Result<(), SyntaxErr> {
if json.len() < *idx + 5 {
return Err(SyntaxErr::unexpected_end(&mut (json.len() + 1)));
};
if json[*idx + 1..=*idx + 4].eq("alse".as_bytes()) {
if json.len() < *idx + 6 {
*idx += 5;
return Ok(());
};
match json[*idx + 5] {
b',' | b' ' | b'}' | b']' | b'\n' | b'\r' | b'\t' => {
*idx += 5;
return Ok(());
}
_ => {
return Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx));
}
};
};
Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx))
}
#[inline]
pub fn skip_null(json: &[u8], idx: &mut usize, exp: &'static str) -> Result<(), SyntaxErr> {
if json.len() < *idx + 4 {
return Err(SyntaxErr::unexpected_end(&mut (json.len() + 1)));
};
if json[*idx + 1..=*idx + 3].eq("ull".as_bytes()) {
if json.len() < *idx + 5 {
*idx += 4;
return Ok(());
};
match json[*idx + 4] {
b',' | b' ' | b'}' | b']' | b'\n' | b'\r' | b'\t' => {
*idx += 4;
return Ok(());
}
_ => {
return Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx));
}
};
};
Err(SyntaxErr::unexpected_token(exp, &[json[*idx]], idx))
}
#[inline]
pub fn skip_array(json: &[u8], idx: &mut usize) -> Result<(), SyntaxErr> {
*idx += 1;
let mut depth = 0;
while json.len() > *idx {
match json[*idx] {
b'[' => {
*idx += 1;
depth += 1;
}
b']' => {
*idx += 1;
if depth == 0 {
return Ok(());
};
depth -= 1;
}
b'"' => {
*idx += 1;
skip_string(json, idx)?;
}
_ => *idx += 1,
}
}
Err(SyntaxErr::unexpected_end(idx))
}
#[inline]
pub fn skip_object(json: &[u8], idx: &mut usize) -> Result<(), SyntaxErr> {
*idx += 1;
let mut depth = 0;
while json.len() > *idx {
match json[*idx] {
b'{' => {
*idx += 1;
depth += 1;
}
b'}' => {
*idx += 1;
if depth == 0 {
return Ok(());
};
depth -= 1;
}
b'"' => {
*idx += 1;
skip_string(json, idx)?;
}
_ => *idx += 1,
}
}
Err(SyntaxErr::unexpected_end(idx))
}
#[inline]
pub fn skip_number(json: &[u8], idx: &mut usize) {
*idx += 1;
while json.len() > *idx {
match json[*idx] {
b',' | b' ' | b'}' | b']' | b'\n' | b'\r' | b'\t' => {
return;
}
_ => *idx += 1,
};
}
}