use crate::{Error, Scanner};
const ASCII_TO_DIGIT: [u8; 256] = {
let mut t = [0xFFu8; 256];
let mut i = b'0';
while i <= b'9' { t[i as usize] = i - b'0'; i += 1; }
t
};
const DIGIT: [u8; 256] = ASCII_TO_DIGIT;
pub trait FromJson<'de>: Sized {
fn from_json_scanner(scanner: &mut Scanner<'de>) -> Result<Self, Error>;
fn from_json_str(s: &'de str) -> Result<Self, Error> {
let mut sc = Scanner::new_str(s);
Self::from_json_scanner(&mut sc)
}
fn from_json_bytes(b: &'de [u8]) -> Result<Self, Error> {
let mut sc = Scanner::new(b);
Self::from_json_scanner(&mut sc)
}
}
impl<'de> FromJson<'de> for &'de str {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.read_str()?.as_borrowed().ok_or(Error::EscapedString)
}
}
impl<'de> FromJson<'de> for String {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.read_str().map(|js| js.into_owned())
}
}
impl<'de> FromJson<'de> for bool {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.read_bool()
}
}
impl<'de, T: FromJson<'de>> FromJson<'de> for Option<T> {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
if sc.peek_null() { sc.read_null()?; Ok(None) } else { T::from_json_scanner(sc).map(Some) }
}
}
impl<'de, T: FromJson<'de>> FromJson<'de> for Vec<T> {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
sc.expect_byte(b'[')?;
if sc.peek_byte_after_ws()? == b']' { sc.advance(); return Ok(Vec::new()); }
let mut out: Vec<T> = Vec::with_capacity(16);
loop {
out.push(T::from_json_scanner(sc)?);
match sc.peek_byte_after_ws()? {
b',' => { sc.advance(); }
b']' => { sc.advance(); break; }
_ => return Err(Error::UnexpectedToken),
}
}
Ok(out)
}
}
impl<'de> FromJson<'de> for u64 {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
let bytes = sc.read_number_bytes()?;
let mut n = 0u64;
let mut overflow = false;
for &b in bytes {
let d = DIGIT[b as usize];
if d == 255 { return Err(Error::InvalidNumber); }
let (next, ovf) = n.overflowing_mul(10);
overflow |= ovf;
let (next2, ovf2) = next.overflowing_add(d as u64);
overflow |= ovf2;
n = next2;
}
if overflow { return Err(Error::InvalidNumber); }
Ok(n)
}
}
macro_rules! impl_uint {
($($t:ty),*) => {$(
impl<'de> FromJson<'de> for $t {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
let bytes = sc.read_number_bytes()?;
let mut n = 0u64;
let mut bad = false;
for &b in bytes {
let d = ASCII_TO_DIGIT[b as usize];
bad |= d == 0xFF;
n = n.wrapping_mul(10).wrapping_add(d as u64);
}
if bad { return Err(Error::InvalidNumber); }
<$t>::try_from(n).map_err(|_| Error::InvalidNumber)
}
}
)*};
}
macro_rules! impl_sint {
($($t:ty),*) => {$(
impl<'de> FromJson<'de> for $t {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
let bytes = sc.read_number_bytes()?;
let (neg, digits) = if bytes.first() == Some(&b'-') { (true, &bytes[1..]) } else { (false, bytes) };
let mut n = 0u64;
let mut bad = false;
for &b in digits {
let d = ASCII_TO_DIGIT[b as usize];
bad |= d == 0xFF;
n = n.wrapping_mul(10).wrapping_add(d as u64);
}
if bad { return Err(Error::InvalidNumber); }
let signed: i64 = if neg {
(n as i64).wrapping_neg()
} else {
n as i64
};
if neg && n > (i64::MAX as u64 + 1) { return Err(Error::InvalidNumber); }
if !neg && n > i64::MAX as u64 { return Err(Error::InvalidNumber); }
<$t>::try_from(signed).map_err(|_| Error::InvalidNumber)
}
}
)*};
}
impl<'de> FromJson<'de> for f64 {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
#[cfg(feature = "fast-float")]
{
let (val, consumed) = fast_float2::parse_partial::<f64, _>(sc.remaining_input())
.map_err(|_| Error::InvalidNumber)?;
sc.advance_by(consumed);
return Ok(val);
}
#[cfg(not(feature = "fast-float"))]
{
let bytes = sc.read_number_bytes()?;
let s = core::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8)?;
s.parse::<f64>().map_err(|_| Error::InvalidNumber)
}
}
}
impl<'de> FromJson<'de> for f32 {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
#[cfg(feature = "fast-float")]
{
let (val, consumed) = fast_float2::parse_partial::<f32, _>(sc.remaining_input())
.map_err(|_| Error::InvalidNumber)?;
sc.advance_by(consumed);
return Ok(val);
}
#[cfg(not(feature = "fast-float"))]
{
let bytes = sc.read_number_bytes()?;
let s = core::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8)?;
s.parse::<f32>().map_err(|_| Error::InvalidNumber)
}
}
}
impl_uint!(u8, u16, u32, usize); impl_sint!(i8, i16, i32, i64, isize);
impl<'de> FromJson<'de> for u128 {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
let bytes = sc.read_number_bytes()?;
let mut n = 0u128;
for &b in bytes {
let d = DIGIT[b as usize];
if d == 0xFF { return Err(Error::InvalidNumber); }
n = n.checked_mul(10)
.and_then(|v| v.checked_add(d as u128))
.ok_or(Error::InvalidNumber)?;
}
Ok(n)
}
}
impl<'de> FromJson<'de> for i128 {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
let bytes = sc.read_number_bytes()?;
let (neg, digits) = if bytes.first() == Some(&b'-') { (true, &bytes[1..]) } else { (false, bytes) };
let mut n = 0i128;
for &b in digits {
let d = DIGIT[b as usize];
if d == 0xFF { return Err(Error::InvalidNumber); }
n = n.checked_mul(10)
.and_then(|v| if neg { v.checked_sub(d as i128) } else { v.checked_add(d as i128) })
.ok_or(Error::InvalidNumber)?;
}
Ok(n)
}
}
impl<'de> FromJson<'de> for char {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
let js = sc.read_str()?;
let s = js.as_str();
let mut chars = s.chars();
let c = chars.next().ok_or(Error::InvalidNumber)?;
if chars.next().is_some() {
return Err(Error::Custom("expected single char".into()));
}
Ok(c)
}
}
impl<'de> FromJson<'de> for () {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
match sc.peek_byte()? {
b'n' => { sc.read_null()?; Ok(()) }
b'{' => {
sc.advance();
sc.skip_whitespace();
sc.expect_byte(b'}')?;
Ok(())
}
_ => Err(Error::UnexpectedToken),
}
}
}
use std::collections::HashMap;
impl<'de, V: FromJson<'de>> FromJson<'de> for HashMap<String, V> {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
sc.expect_byte(b'{')?;
let mut map = HashMap::with_capacity(8);
loop {
match sc.peek_byte_after_ws()? {
b'}' => { sc.advance(); break; }
b'"' => {
let key_bytes = sc.read_key_colon()?;
let key = core::str::from_utf8(key_bytes)
.map_err(|_| Error::InvalidUtf8)?
.to_owned();
let val = V::from_json_scanner(sc)?;
map.insert(key, val);
match sc.peek_byte_after_ws()? {
b',' => { sc.advance(); }
b'}' => {}
_ => return Err(Error::UnexpectedToken),
}
}
_ => return Err(Error::UnexpectedToken),
}
}
Ok(map)
}
}
impl<'de, V: FromJson<'de>> FromJson<'de> for HashMap<&'de str, V> {
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
sc.expect_byte(b'{')?;
let mut map = HashMap::new();
loop {
match sc.peek_byte_after_ws()? {
b'}' => { sc.advance(); break; }
b'"' => {
let key = sc.read_str()?;
let key_str = key.as_borrowed().ok_or(Error::EscapedString)?;
sc.skip_whitespace();
sc.expect_byte(b':')?;
let val = V::from_json_scanner(sc)?;
map.insert(key_str, val);
match sc.peek_byte_after_ws()? {
b',' => { sc.advance(); }
b'}' => {}
_ => return Err(Error::UnexpectedToken),
}
}
_ => return Err(Error::UnexpectedToken),
}
}
Ok(map)
}
}
use std::collections::BTreeMap;
impl<'de, V: FromJson<'de>> FromJson<'de> for BTreeMap<String, V> {
#[inline]
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace();
sc.expect_byte(b'{')?;
let mut map = BTreeMap::new();
loop {
match sc.peek_byte_after_ws()? {
b'}' => { sc.advance(); break; }
b'"' => {
let key_bytes = sc.read_key_colon()?;
let key = core::str::from_utf8(key_bytes)
.map_err(|_| Error::InvalidUtf8)?
.to_owned();
let val = V::from_json_scanner(sc)?;
map.insert(key, val);
match sc.peek_byte_after_ws()? {
b',' => { sc.advance(); }
b'}' => {}
_ => return Err(Error::UnexpectedToken),
}
}
_ => return Err(Error::UnexpectedToken),
}
}
Ok(map)
}
}
macro_rules! impl_tuple_from_json {
($first:ident . $fv:ident $(, $T:ident . $v:ident)*) => {
impl<'de, $first: FromJson<'de> $(, $T: FromJson<'de>)*> FromJson<'de>
for ($first, $($T,)*)
{
fn from_json_scanner(sc: &mut Scanner<'de>) -> Result<Self, Error> {
sc.skip_whitespace(); sc.expect_byte(b'[')?;
let $fv = $first::from_json_scanner(sc)?;
$(
sc.skip_whitespace(); sc.expect_byte(b',')?;
let $v = $T::from_json_scanner(sc)?;
)*
sc.skip_whitespace(); sc.expect_byte(b']')?;
Ok(($fv, $($v,)*))
}
}
};
}
impl_tuple_from_json!(A.a0);
impl_tuple_from_json!(A.a0, B.b1);
impl_tuple_from_json!(A.a0, B.b1, C.c2);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6, H.h7);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6, H.h7, I.i8);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6, H.h7, I.i8, J.j9);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6, H.h7, I.i8, J.j9, K.k10);
impl_tuple_from_json!(A.a0, B.b1, C.c2, D.d3, E.e4, F.f5, G.g6, H.h7, I.i8, J.j9, K.k10, L.l11);