microjson 0.1.6

No frills JSON parsing without allocations
Documentation
const POWERS_OF_TEN: [f32; 39] = [
    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16,
    1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32,
    1e33, 1e34, 1e35, 1e36, 1e37, 1e38,
];
pub fn parse_float(value: &str) -> Result<f32, ()> {
    let mut chars = value.chars().peekable();
    let positive = match chars.peek() {
        Some('-') => {
            chars.next();
            if chars.peek().is_none() {
                return Err(());
            }
            false
        }
        Some(_) => true,
        _ => return Err(()),
    };
    let mut value = 0.;
    let mut next_digit_size = 0.1;
    let mut exponent = 0;
    let mut seen_decimal = false;
    let mut seen_exponent = false;
    while let Some(c) = chars.next() {
        match c {
            '0'..='9' => {
                if !seen_decimal {
                    exponent += 1;
                }
                value += next_digit_size * c.to_digit(10).unwrap() as f32;
                next_digit_size *= 0.1;
            }
            '.' => {
                if seen_decimal || seen_exponent {
                    return Err(());
                } else {
                    seen_decimal = true;
                }
            }
            'e' | 'E' => {
                seen_exponent = true;
                break;
            }
            _ => return Err(()),
        }
    }
    if seen_exponent {
        let mut explicit_exponent = 0;
        let exponent_positive = match chars.peek() {
            Some('-' | '+') => chars.next() == Some('+'),
            Some('0'..='9') => true,
            _ => return Err(()),
        };
        for c in chars {
            match c {
                '0'..='9' => {
                    explicit_exponent *= 10;
                    explicit_exponent += c.to_digit(10).unwrap() as i32;
                }
                _ => return Err(()),
            }
        }
        if !exponent_positive {
            explicit_exponent = -explicit_exponent;
        }
        exponent += explicit_exponent;
    }
    if exponent < -37 || exponent > 38 {
        return Err(());
    }
    if 0 < exponent {
        value = value * POWERS_OF_TEN[exponent as usize];
    } else if exponent < 0 {
        value = value / POWERS_OF_TEN[exponent.abs() as usize];
    }

    if !positive {
        value = -value;
    }
    Ok(value)
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::parse_float;
    use std::string::ToString;

    fn close(a: f32, b: f32) -> bool {
        if f32::min(a, b) == 0. {
            a == 0. && b == 0.
        } else {
            f32::abs((a - b) / f32::min(a, b)) < 0.000001
        }
    }

    #[test]
    fn errors() {
        assert!(parse_float("").is_err());
        assert!(parse_float("-").is_err());
        assert!(parse_float("foo").is_err());
        assert!(parse_float("1.23.4").is_err());
        assert!(parse_float("10e0.3").is_err());
    }

    #[test]
    fn zeros() {
        assert_eq!(parse_float("0").unwrap(), 0f32);
        assert_eq!(parse_float("-0").unwrap(), 0f32);
        assert_eq!(parse_float("0e1").unwrap(), 0f32);
        assert_eq!(parse_float("-0e1").unwrap(), 0f32);
        assert_eq!(parse_float("0e-1").unwrap(), 0f32);
        assert_eq!(parse_float("-0e-1").unwrap(), 0f32);
        assert_eq!(parse_float("0E1").unwrap(), 0f32);
        assert_eq!(parse_float("-0E1").unwrap(), 0f32);
        assert_eq!(parse_float("0E+1").unwrap(), 0f32);
        assert_eq!(parse_float("-0E+1").unwrap(), 0f32);
        assert_eq!(parse_float("0E-1").unwrap(), 0f32);
        assert_eq!(parse_float("-0E-1").unwrap(), 0f32);
    }

    #[test]
    fn exponents() {
        assert!(close(parse_float("1").unwrap(), 1f32));
        assert!(close(parse_float("10").unwrap(), 10f32));
        assert!(close(parse_float("100").unwrap(), 100f32));
        assert!(close(parse_float("1e2").unwrap(), 100f32));
        assert!(close(parse_float("1E2").unwrap(), 100f32));
        assert!(close(parse_float("0.1e3").unwrap(), 100f32));
        assert!(close(parse_float("1000e-1").unwrap(), 100f32));
        assert!(close(parse_float("1E00").unwrap(), 1f32));
        assert!(close(parse_float("1E001").unwrap(), 10f32));
    }

    #[test]
    fn manual() {
        assert!(close(parse_float("3.141592").unwrap(), 3.141592f32));
        assert!(close(parse_float("3.141592e-2").unwrap(), 0.03141592f32));
        assert!(close(parse_float("3.141592e+2").unwrap(), 314.1592f32));
        assert!(close(parse_float("3").unwrap(), 3f32));
    }

    #[test]
    fn logistic() {
        let mut t = 0.234;
        for _ in 0..400 {
            let s = 2. * (t - 0.5);
            assert!(close(s, parse_float(&s.to_string()).unwrap()));
            t = 3.8 * t * (1. - t);
        }
    }

    #[test]
    fn integers() {
        for t in -2000000..2000000 {
            assert!(close(t as f32, parse_float(&t.to_string()).unwrap()));
        }
    }

    #[test]
    fn overflows() {
        assert!(parse_float("1e39").is_err());
        assert!(parse_float("10000000000000000000000000000000000000000").is_err());
        assert!(parse_float("-10000000000000000000000000000000000000000").is_err());
        assert!(parse_float("1e-39").is_err());
    }
}