use core::str;
use super::error::{JsonError, JsonErrorKind};
use super::lexer::Cursor;
pub(crate) fn parse_number(cursor: &mut Cursor<'_>) -> Result<f64, JsonError> {
let start = cursor.position();
cursor.try_consume(b'-');
let first = cursor
.peek()
.ok_or(JsonError::new(JsonErrorKind::Eof, cursor.position()))?;
match first {
b'0' => {
cursor.advance(1);
}
b'1'..=b'9' => {
cursor.advance(1);
while matches!(cursor.peek(), Some(b'0'..=b'9')) {
cursor.advance(1);
}
}
_ => {
return Err(JsonError::new(
JsonErrorKind::InvalidNumber,
cursor.position(),
))
}
}
if cursor.try_consume(b'.') {
let mut digits = 0usize;
while matches!(cursor.peek(), Some(b'0'..=b'9')) {
cursor.advance(1);
digits += 1;
}
if digits == 0 {
return Err(JsonError::new(
JsonErrorKind::InvalidNumber,
cursor.position(),
));
}
}
if matches!(cursor.peek(), Some(b'e') | Some(b'E')) {
cursor.advance(1);
if matches!(cursor.peek(), Some(b'+') | Some(b'-')) {
cursor.advance(1);
}
let mut digits = 0usize;
while matches!(cursor.peek(), Some(b'0'..=b'9')) {
cursor.advance(1);
digits += 1;
}
if digits == 0 {
return Err(JsonError::new(
JsonErrorKind::InvalidNumber,
cursor.position(),
));
}
}
let end = cursor.position();
let s = str::from_utf8(&cursor.bytes()[start..end])
.map_err(|_| JsonError::new(JsonErrorKind::InvalidUtf8, start))?;
s.parse::<f64>()
.map_err(|_| JsonError::new(JsonErrorKind::InvalidNumber, start))
}