fn scan_value(data: &[u8], vstart: usize) -> &[u8] {
let mut depth: i32 = 0;
let mut in_str = false;
let mut esc = false;
let mut i = vstart;
while i < data.len() {
let c = data[i];
if esc {
esc = false;
i += 1;
continue;
}
if c == b'\\' {
esc = true;
i += 1;
continue;
}
if c == b'"' {
in_str = !in_str;
i += 1;
continue;
}
if in_str {
i += 1;
continue;
}
if c == b'{' || c == b'[' {
depth += 1;
} else if c == b'}' || c == b']' {
if depth == 0 {
return &data[vstart..i];
}
depth -= 1;
} else if c == b',' && depth == 0 {
return &data[vstart..i];
}
i += 1;
}
&data[vstart..data.len()]
}
pub fn json_field<'a>(data: &'a [u8], key: &[u8]) -> &'a [u8] {
let klen = key.len();
let mut depth: i32 = 0;
let mut in_str = false;
let mut esc = false;
let mut i: usize = 0;
while i + klen + 3 < data.len() {
let c = data[i];
if esc {
esc = false;
i += 1;
continue;
}
if c == b'\\' {
esc = true;
i += 1;
continue;
}
if c == b'"' {
if !in_str
&& depth == 1
&& &data[i + 1..i + 1 + klen] == key
&& data[i + klen + 1] == b'"'
&& data[i + klen + 2] == b':'
{
return scan_value(data, i + klen + 3);
}
in_str = !in_str;
i += 1;
continue;
}
if in_str {
i += 1;
continue;
}
if c == b'{' || c == b'[' {
depth += 1;
} else if c == b'}' || c == b']' {
depth -= 1;
}
i += 1;
}
&[]
}
pub fn json_id(data: &[u8]) -> u64 {
let slice = json_field(data, b"id");
if slice.is_empty() {
return 0;
}
let mut n: u64 = 0;
for &c in slice {
if !c.is_ascii_digit() {
break;
}
n = n * 10 + u64::from(c - b'0');
}
n
}
pub fn json_string(field: &[u8]) -> &[u8] {
let f = field
.iter()
.position(|&b| b != b' ' && b != b'\t')
.map_or(field, |s| &field[s..]);
let f = f.iter().rposition(|&b| b != b' ' && b != b'\t').map_or(f, |e| &f[..=e]);
if f.len() >= 2 && f[0] == b'"' && f[f.len() - 1] == b'"' {
&f[1..f.len() - 1]
} else {
&[]
}
}
pub fn error_message(error_field: &[u8]) -> &[u8] {
json_string(json_field(error_field, b"message"))
}