| 188 | } |
| 189 | |
| 190 | fn parse_number(&self, s: &str, vm: &VirtualMachine) -> Option<(PyResult, usize)> { |
| 191 | flame_guard!("JsonScanner::parse_number"); |
| 192 | let mut has_neg = false; |
| 193 | let mut has_decimal = false; |
| 194 | let mut has_exponent = false; |
| 195 | let mut has_e_sign = false; |
| 196 | let mut i = 0; |
| 197 | for c in s.chars() { |
| 198 | match c { |
| 199 | '-' if i == 0 => has_neg = true, |
| 200 | n if n.is_ascii_digit() => {} |
| 201 | '.' if !has_decimal => has_decimal = true, |
| 202 | 'e' | 'E' if !has_exponent => has_exponent = true, |
| 203 | '+' | '-' if !has_e_sign => has_e_sign = true, |
| 204 | _ => break, |
| 205 | } |
| 206 | i += 1; |
| 207 | } |
| 208 | if i == 0 || (i == 1 && has_neg) { |
| 209 | return None; |
| 210 | } |
| 211 | let buf = &s[..i]; |
| 212 | let ret = if has_decimal || has_exponent { |
| 213 | // float |
| 214 | if let Some(ref parse_float) = self.parse_float { |
| 215 | parse_float.call((buf,), vm) |
| 216 | } else { |
| 217 | Ok(vm.ctx.new_float(f64::from_str(buf).unwrap()).into()) |
| 218 | } |
| 219 | } else if let Some(ref parse_int) = self.parse_int { |
| 220 | parse_int.call((buf,), vm) |
| 221 | } else { |
| 222 | Ok(vm.new_pyobj(BigInt::from_str(buf).unwrap())) |
| 223 | }; |
| 224 | Some((ret, buf.len())) |
| 225 | } |
| 226 | |
| 227 | /// Parse a JSON object starting after the opening '{'. |
| 228 | /// Returns (parsed_object, end_char_index, end_byte_index). |