from 0.1.4

A procedural macro that generates custom parsing and validation code
Documentation
use super::{utils, SyntaxErr};

pub fn parse<'a>(json: &'a [u8], idx: &mut usize) -> Result<&'a [u8], SyntaxErr> {
    let mut byte = utils::get_or_unexpected_end(json, idx)?;

    if byte.ne(&b'"') {
        return Err(SyntaxErr::unexpected_token("\"", &[byte], idx));
    };

    *idx += 1;

    let begin = *idx;

    byte = utils::get_or_unexpected_end(json, idx)?;

    match byte {
        b'a'..=b'z' | b'A'..=b'Z' | b'_' => {}

        _ => {
            return Err(SyntaxErr::unexpected_token(
                "alphabet character or underscore",
                &[byte],
                idx,
            ));
        }
    };

    loop {
        *idx += 1;

        byte = utils::get_or_unexpected_end(json, idx)?;

        match byte {
            b'a'..=b'z' | b'A'..=b'Z' | b'_' | b'0'..=b'9' => {}

            b'"' => {
                *idx += 1;
                return Ok(&json[begin..*idx - 1]);
            }

            _ => {
                return Err(SyntaxErr::unexpected_token(
                    "alphabet character, underscore or digit",
                    &[byte],
                    idx,
                ));
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{parse, SyntaxErr};
    #[test]
    fn valid() {
        assert_eq!(
            parse(r#""prop""#.as_bytes(), &mut 0),
            Ok(b"prop".as_slice()),
        );

        assert_eq!(
            parse(r#""_prop""#.as_bytes(), &mut 0),
            Ok(b"_prop".as_slice()),
        );

        assert_eq!(
            parse(r#""_12prop45""#.as_bytes(), &mut 0),
            Ok(b"_12prop45".as_slice()),
        );

        assert_eq!(
            parse(r#""_12prop45""#.as_bytes(), &mut 0),
            Ok(b"_12prop45".as_slice()),
        );
    }

    #[test]
    fn syntax_err() {
        assert_eq!(
            parse(r#"as"#.as_bytes(), &mut 0),
            Err(SyntaxErr::new("expected: \", found: a", &mut 0)),
        );

        assert_eq!(
            parse(r#""17asf""#.as_bytes(), &mut 0),
            Err(SyntaxErr::new(
                "expected: alphabet character or underscore, found: 1",
                &mut 1
            )),
        );

        assert_eq!(
            parse(r#""abcd"#.as_bytes(), &mut 0),
            Err(SyntaxErr::unexpected_end(&mut 5)),
        );

        assert_eq!(
            parse(r#""abcd#""#.as_bytes(), &mut 0),
            Err(SyntaxErr::unexpected_token(
                "alphabet character, underscore or digit",
                &[b'#'],
                &mut 5
            )),
        );
    }
}