pub(crate) struct Number {
pub positive: bool,
pub numerator: u128,
pub base2_exponent: i16,
pub base10_exponent: i16,
}
impl Number {
fn to_int(&self, source: &str) -> Result<u128, crate::DeserializeErrorKind> {
let mut n = self.numerator;
if self.base2_exponent < 0 {
n = n.checked_shr(-self.base2_exponent as u32)
.ok_or_else(|| crate::DeserializeErrorKind::IntFraction(source.into()))?;
} else if self.base2_exponent > 0 {
n = n.checked_shl(self.base2_exponent as u32)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(source.into()))?;
}
if self.base10_exponent < 0 {
let pow = 10u128.checked_pow((-self.base10_exponent) as u32)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(source.into()))?;
if n % pow != 0 {
return Err(crate::DeserializeErrorKind::IntFraction(source.into()));
}
n /= pow;
} else if self.base10_exponent > 0 {
let pow = 10u128.checked_pow(self.base10_exponent as u32)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(source.into()))?;
n = n.checked_mul(pow)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(source.into()))?;
}
Ok(n)
}
pub fn to_sint<
T: std::convert::TryFrom<i128> + std::ops::Neg
>(
&self,
source: &str,
) -> Result<T, crate::DeserializeErrorKind>
where
<T as std::convert::TryFrom<i128>>::Error: std::fmt::Debug,
<T as std::ops::Neg>::Output: std::convert::Into<T>,
{
let mut i;
if !self.positive && self.numerator == (i128::max_value() as u128) + 1 {
i = i128::min_value();
} else {
i = self.to_uint(source)?;
if !self.positive {
i = (-i).into();
}
}
return T::try_from(i)
.map_err(|_| crate::DeserializeErrorKind::IntOverflow(source.into()))
}
pub fn to_uint<T: std::convert::TryFrom<u128>>(&self, source: &str)
-> Result<T, crate::DeserializeErrorKind>
where
<T as std::convert::TryFrom<u128>>::Error: std::fmt::Debug,
{
T::try_from(self.to_int(source)?)
.map_err(|_| crate::DeserializeErrorKind::IntOverflow(source.into()))
}
pub fn to_f64(&self) -> f64 {
let mut n = self.numerator as f64;
if !self.positive {
n = -n;
}
n *= 2f64.powi(self.base2_exponent.into());
n *= 10f64.powi(self.base10_exponent.into());
n
}
}
pub(crate) fn parse_num(mut s: &str, location: crate::Location) -> Result<Number, crate::de::DeserializeError> {
let positive = if s.starts_with('-') {
s = &s[1..];
false
} else {
true
};
if s.is_empty() {
return Err(crate::de::DeserializeErrorKind::Invalid(
"Can't parse \"\" as a number.".into())
.at(location))
}
let mut bytes = s.as_bytes();
let (base, consume) = match (bytes[0], bytes.get(1)) {
(b'0', Some(b'b')) => (2, 2),
(b'0', Some(b'd')) => (10, 2),
(b'0', Some(b'o')) => (8, 2),
(b'0', Some(b'x')) => (16, 2),
(b'0', _) => (10, 1),
_ => (10, 0),
};
bytes = &bytes[consume..];
let (mut n, len) = parse_num_base(base, bytes)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
bytes = &bytes[len as usize..];
let mut base2_exponent = 0i16;
let mut base10_exponent = 0i16;
if bytes.get(0) == Some(&b'.') {
let (d, d_len) = parse_num_base(base, &bytes[1..])
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
n = (base as u128).checked_pow(d_len as u32)
.and_then(|e| e.checked_mul(n))
.and_then(|n| n.checked_add(d))
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
match base {
2 => {
base2_exponent = base2_exponent.checked_sub(d_len)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
}
8 => {
base2_exponent = d_len.checked_mul(3)
.and_then(|e| base2_exponent.checked_sub(e))
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
}
10 => {
base10_exponent = base10_exponent.checked_sub(d_len)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
}
16 => {
base2_exponent = d_len.checked_mul(4)
.and_then(|e| base2_exponent.checked_sub(e))
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
}
_ => unreachable!(),
}
bytes = &bytes[1 + d_len as usize..];
}
let (b2, b10) = parse_num_exponent(base, bytes, location)?;
base2_exponent = base2_exponent.checked_add(b2)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
base10_exponent = base10_exponent.checked_add(b10)
.ok_or_else(|| crate::DeserializeErrorKind::IntOverflow(s.into()).at(location))?;
Ok(Number {
positive,
numerator: n,
base2_exponent,
base10_exponent,
})
}
fn parse_num_base(base: u8, bytes: &[u8]) -> Option<(u128, i16)> {
let mut n = 0u128;
let mut len = 0i16;
while let Some(c) = bytes.get(len as usize) {
match c {
b'_' => {}
b'0'..=b'9' |
b'a'..=b'f' |
b'A'..=b'F' => {
if let Some(d) = (*c as char).to_digit(base.into()) {
n = n.checked_mul(base.into())?
.checked_add(d.into())?;
} else {
break
}
}
_ => break,
}
len += 1;
}
Some((n, len))
}
fn parse_num_exponent(base: u8, bytes: &[u8], mut location: crate::Location) -> Result<(i16, i16), crate::de::DeserializeError> {
let s = unsafe { crate::from_utf8_unchecked(bytes) };
let mut bindec = move |s: &str, bin, dec| {
match s.len() {
0 => Ok((0, dec)),
1 if bytes[1] == b'i' => Ok((bin, 0)),
_ => {
location.add_columns(2);
Err(crate::de::DeserializeErrorKind::NumTrailing(s.into()).at(location))
}
}
};
match s.chars().next() {
Some('E') => bindec(&s[1..], 60, 18),
Some('P') => bindec(&s[1..], 50, 15),
Some('T') => bindec(&s[1..], 40, 12),
Some('G') => bindec(&s[1..], 30, 9),
Some('M') => bindec(&s[1..], 20, 6),
Some('K') => bindec(&s[1..], 10, 3), Some('k') => bindec(&s[1..], 10, 3),
Some('m') => bindec(&s[1..], 10, 3),
Some('u') => bindec(&s[1..], 20, 6),
Some('µ') => bindec(&s['µ'.len_utf8()..], 30, 9),
Some('n') => bindec(&s[1..], 40, 12),
Some('p') => bindec(&s[1..], 50, 15),
Some('f') => bindec(&s[1..], 60, 18),
Some('a') => bindec(&s[1..], 70, 21),
Some('e') => {
if base != 10 {
return Err(crate::de::DeserializeErrorKind::NumExpBase.at(location))
}
location.add_columns(1);
let e = s[1..].parse()
.map_err(|e| crate::DeserializeErrorKind::NumExpInvalid(e).at(location))?;
Ok((0, e))
}
Some(_) => Err(crate::de::DeserializeErrorKind::NumTrailing(s.into()).at(location)),
None => Ok((0, 0)),
}
}