use crate::{Kind, Lex, Lexer, Token};

#[test]
fn lex() {
    let cases: Vec<Lex> = vec![
        Lex::new("", vec![]),
        Lex::new("你好", vec![Token::new(Kind::NonAscii, "你好", 0, 0)]),
        Lex::new(
            "你好\x7F",
            vec![
                Token::new(Kind::NonAscii, "你好", 0, 0),
                Token::new(Kind::Controls, "\x7F", 0, 6),
            ],
        ),
        Lex::new("\r", vec![Token::new(Kind::LineEnding, "\r", 0, 0)]),
        Lex::new("\n", vec![Token::new(Kind::LineEnding, "\n", 0, 0)]),
        Lex::new(
            "\r ",
            vec![
                Token::new(Kind::LineEnding, "\r", 0, 0),
                Token::new(Kind::Whitespace, " ", 1, 0),
            ],
        ),
        Lex::new(
            "\n ",
            vec![
                Token::new(Kind::LineEnding, "\n", 0, 0),
                Token::new(Kind::Whitespace, " ", 1, 0),
            ],
        ),
        Lex::new("\r\n", vec![Token::new(Kind::LineEnding, "\r\n", 0, 0)]),
        Lex::new(
            "\r\n ",
            vec![
                Token::new(Kind::LineEnding, "\r\n", 0, 0),
                Token::new(Kind::Whitespace, " ", 1, 0),
            ],
        ),
        Lex::new(
            "\r\r\n ",
            vec![
                Token::new(Kind::LineEnding, "\r", 0, 0),
                Token::new(Kind::LineEnding, "\r\n", 1, 0),
                Token::new(Kind::Whitespace, " ", 2, 0),
            ],
        ),
        Lex::new(" \t ", vec![Token::new(Kind::Whitespace, " \t ", 0, 0)]),
        Lex::new(
            " \t a",
            vec![
                Token::new(Kind::Whitespace, " \t ", 0, 0),
                Token::new(Kind::Symbol, "a", 0, 3),
            ],
        ),
        Lex::new(
            "\x00\r\x1F\n\x7F\t\x00",
            vec![
                Token::new(Kind::Controls, "\x00", 0, 0),
                Token::new(Kind::LineEnding, "\r", 0, 1),
                Token::new(Kind::Controls, "\x1F", 1, 0),
                Token::new(Kind::LineEnding, "\n", 1, 1),
                Token::new(Kind::Controls, "\x7F", 2, 0),
                Token::new(Kind::Whitespace, "\t", 2, 1),
                Token::new(Kind::Controls, "\x00", 2, 2),
            ],
        ),
        Lex::new("azAZ09_", vec![Token::new(Kind::Symbol, "azAZ09_", 0, 0)]),
        Lex::new(
            "azAZ09_ ",
            vec![
                Token::new(Kind::Symbol, "azAZ09_", 0, 0),
                Token::new(Kind::Whitespace, " ", 0, 7),
            ],
        ),
        Lex::new(
            "!/:@[`{~",
            vec![
                Token::new(Kind::Special(b'!'), "!", 0, 0),
                Token::new(Kind::Special(b'/'), "/", 0, 1),
                Token::new(Kind::Special(b':'), ":", 0, 2),
                Token::new(Kind::Special(b'@'), "@", 0, 3),
                Token::new(Kind::Special(b'['), "[", 0, 4),
                Token::new(Kind::Special(b'`'), "`", 0, 5),
                Token::new(Kind::Special(b'{'), "{", 0, 6),
                Token::new(Kind::Special(b'~'), "~", 0, 7),
            ],
        ),
    ];
    let lexer: Lexer = Lexer::new();
    for (i, lex) in cases.iter().enumerate() {
        let result: Lex = lexer.lex(lex.source());
        assert_eq!(result.tokens(), lex.tokens(), "{}", i);
    }
}
