use snapbox::prelude::*;
use snapbox::str;

use crate::ascii::dec_uint;
use crate::ascii::digit0;
use crate::combinator::dispatch;
use crate::combinator::empty;
use crate::combinator::fail;
use crate::combinator::seq;
use crate::combinator::unordered_seq;
use crate::prelude::*;
use crate::stream::Partial;
use crate::token::any;

#[test]
fn dispatch_basics() {
    fn escape_seq_char<'i>(input: &mut &'i str) -> TestResult<&'i str, char> {
        dispatch! {any;
            'b' => empty.value('\u{8}'),
            'f' => empty.value('\u{c}'),
            'n' => empty.value('\n'),
            'r' => empty.value('\r'),
            't' => empty.value('\t'),
            '\\' => empty.value('\\'),
            '"' => empty.value('"'),
            _ => fail::<_, char, _>,
        }
        .parse_next(input)
    }
    assert_parse!(
        escape_seq_char.parse_peek("b123"),
        str![[r#"
Ok(
    (
        "123",
        '\u{8}',
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        escape_seq_char.parse_peek("error"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "rror",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        escape_seq_char.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_struct_basics() {
    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
            }
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point {
            x: 123,
            y: 4,
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_struct_default_init() {
    #[derive(Debug, PartialEq, Default)]
    struct Point {
        x: u32,
        y: u32,
        z: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                ..Default::default()
            }
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point {
            x: 123,
            y: 4,
            z: 0,
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_struct_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty,
            }
        }
        .parse_next(input)
    }
}

#[test]
fn seq_struct_no_trailing_comma() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint
            }
        }
        .parse_next(input)
    }
}

#[test]
fn seq_struct_no_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty
            }
        }
        .parse_next(input)
    }
}

#[test]
fn seq_enum_struct_variant() {
    #[derive(Debug, PartialEq, Eq)]
    enum Expr {
        Add { lhs: u32, rhs: u32 },
        Mul(u32, u32),
    }

    fn add<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], Expr> {
        seq! {Expr::Add {
            lhs: dec_uint::<_, u32, _>,
            _: b" + ",
            rhs: dec_uint::<_, u32, _>,
        }}
        .parse_next(input)
    }

    fn mul<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], Expr> {
        seq!(Expr::Mul(
             dec_uint::<_, u32, _>,
             _: b" * ",
             dec_uint::<_, u32, _>,
        ))
        .parse_next(input)
    }

    assert_parse!(
        add.parse_peek(&b"1 + 2"[..]),
        str![[r#"
Ok(
    (
        [],
        Add {
            lhs: 1,
            rhs: 2,
        },
    ),
)

"#]]
        .raw()
    );

    assert_parse!(
        mul.parse_peek(&b"3 * 4"[..]),
        str![[r#"
Ok(
    (
        [],
        Mul(
            3,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_struct_borrow() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        let mut dec_uint = digit0.parse_to();
        seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty
            }
        }
        .parse_next(input)
    }
}

#[test]
fn seq_struct_many_fields() {
    #[derive(Debug, PartialEq)]
    struct Fields {
        field_00: u8,
        field_01: u8,
        field_02: u8,
        field_03: u8,
        field_04: u8,
        field_05: u8,
        field_06: u8,
        field_07: u8,
        field_08: u8,
        field_09: u8,
        field_10: u8,
        field_11: u8,
        field_12: u8,
        field_13: u8,
        field_14: u8,
        field_15: u8,
        field_16: u8,
        field_17: u8,
        field_18: u8,
        field_19: u8,
        field_20: u8,
        field_21: u8,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Fields> {
        seq! {
            Fields {
                field_00: empty.value(0),
                field_01: empty.value(1),
                field_02: empty.value(2),
                field_03: empty.value(3),
                field_04: empty.value(4),
                field_05: empty.value(5),
                field_06: empty.value(6),
                field_07: empty.value(7),
                field_08: empty.value(8),
                field_09: empty.value(9),
                field_10: empty.value(10),
                field_11: empty.value(11),
                field_12: empty.value(12),
                field_13: empty.value(13),
                field_14: empty.value(14),
                field_15: empty.value(15),
                field_16: empty.value(16),
                field_17: empty.value(17),
                field_18: empty.value(18),
                field_19: empty.value(19),
                field_20: empty.value(20),
                field_21: empty.value(21),
            }
        }
        .parse_next(input)
    }

    assert_parse!(
        parser.parse_peek("remaining"),
        str![[r#"
Ok(
    (
        "remaining",
        Fields {
            field_00: 0,
            field_01: 1,
            field_02: 2,
            field_03: 3,
            field_04: 4,
            field_05: 5,
            field_06: 6,
            field_07: 7,
            field_08: 8,
            field_09: 9,
            field_10: 10,
            field_11: 11,
            field_12: 12,
            field_13: 13,
            field_14: 14,
            field_15: 15,
            field_16: 16,
            field_17: 17,
            field_18: 18,
            field_19: 19,
            field_20: 20,
            field_21: 21,
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_tuple_struct_basics() {
    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
            )
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point(
            123,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_tuple_struct_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty,
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_struct_no_trailing_comma() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_struct_no_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_basics() {
    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
            )
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        (
            123,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn seq_tuple_trailing_comma_elided() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
                _: empty,
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_no_trailing_comma() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        seq! {
            (
                dec_uint,
                _: ',',
                dec_uint
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_no_trailing_comma_elided() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_no_parens() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        seq! (
            dec_uint,
            _: ',',
            dec_uint,
        )
        .parse_next(input)
    }
}

#[test]
fn seq_tuple_borrow() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        let mut dec_uint = digit0.parse_to();
        seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_struct_basics() {
    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
            }
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point {
            x: 123,
            y: 4,
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn unordered_seq_struct_default_init() {
    #[derive(Debug, PartialEq, Default)]
    struct Point {
        x: u32,
        y: u32,
        z: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                ..Default::default()
            }
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point {
            x: 123,
            y: 4,
            z: 0,
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn unordered_seq_struct_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty,
            }
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_struct_no_trailing_comma() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint
            }
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_struct_no_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty
            }
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_enum_struct_variant() {
    #[derive(Debug, PartialEq, Eq)]
    enum Expr {
        Add { lhs: u32, rhs: u32 },
        Mul(u32, u32),
    }

    fn add<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], Expr> {
        unordered_seq! {Expr::Add {
            lhs: dec_uint::<_, u32, _>,
            _: b" + ",
            rhs: dec_uint::<_, u32, _>,
        }}
        .parse_next(input)
    }

    fn mul<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], Expr> {
        unordered_seq!(Expr::Mul(
             dec_uint::<_, u32, _>,
             _: b" * ",
             dec_uint::<_, u32, _>,
        ))
        .parse_next(input)
    }

    assert_parse!(
        add.parse_peek(&b"1 + 2"[..]),
        str![[r#"
Ok(
    (
        [],
        Add {
            lhs: 1,
            rhs: 2,
        },
    ),
)

"#]]
        .raw()
    );

    assert_parse!(
        mul.parse_peek(&b"3 * 4"[..]),
        str![[r#"
Ok(
    (
        [],
        Mul(
            3,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn unordered_seq_struct_borrow() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point {
        x: u32,
        y: u32,
    }

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        let mut dec_uint = digit0.parse_to();
        unordered_seq! {
            Point {
                x: dec_uint,
                _: ',',
                y: dec_uint,
                _: empty
            }
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_struct_basics() {
    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
            )
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        Point(
            123,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn unordered_seq_tuple_struct_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty,
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_struct_no_trailing_comma() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_struct_no_trailing_comma_elided() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        unordered_seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_basics() {
    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        unordered_seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
            )
        }
        .parse_next(input)
    }
    assert_parse!(
        parser.parse_peek("123,4 remaining"),
        str![[r#"
Ok(
    (
        " remaining",
        (
            123,
            4,
        ),
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek("123, remaining"),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: " remaining",
        },
    ),
)

"#]]
        .raw()
    );
    assert_parse!(
        parser.parse_peek(""),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: "",
        },
    ),
)

"#]]
        .raw()
    );
}

#[test]
fn unordered_seq_tuple_trailing_comma_elided() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        unordered_seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
                _: empty,
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_no_trailing_comma() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        unordered_seq! {
            (
                dec_uint,
                _: ',',
                dec_uint
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_no_trailing_comma_elided() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        unordered_seq! {
            (
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_no_parens() {
    #![allow(dead_code)]

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, (u32, u32)> {
        unordered_seq! (
            dec_uint,
            _: ',',
            dec_uint,
        )
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_tuple_borrow() {
    #![allow(dead_code)]

    #[derive(Debug, PartialEq)]
    struct Point(u32, u32);

    fn parser<'i>(input: &mut &'i str) -> TestResult<&'i str, Point> {
        let mut dec_uint = digit0.parse_to();
        unordered_seq! {
            Point(
                dec_uint,
                _: ',',
                dec_uint,
                _: empty
            )
        }
        .parse_next(input)
    }
}

#[test]
fn unordered_seq_permutation_test() {
    #[allow(clippy::type_complexity)]
    fn perm<'i>(
        i: &mut Partial<&'i [u8]>,
    ) -> TestResult<Partial<&'i [u8]>, (&'i [u8], &'i [u8], &'i [u8])> {
        unordered_seq!(("abcd", "efg", "hi")).parse_next(i)
    }

    let a = &b"abcdefghijk"[..];
    assert_parse!(
        perm.parse_peek(Partial::new(a)),
        str![[r#"
Ok(
    (
        Partial {
            input: [
                106,
                107,
            ],
            partial: true,
        },
        (
            [
                97,
                98,
                99,
                100,
            ],
            [
                101,
                102,
                103,
            ],
            [
                104,
                105,
            ],
        ),
    ),
)

"#]]
        .raw()
    );
    let b = &b"efgabcdhijk"[..];
    assert_parse!(
        perm.parse_peek(Partial::new(b)),
        str![[r#"
Ok(
    (
        Partial {
            input: [
                106,
                107,
            ],
            partial: true,
        },
        (
            [
                97,
                98,
                99,
                100,
            ],
            [
                101,
                102,
                103,
            ],
            [
                104,
                105,
            ],
        ),
    ),
)

"#]]
        .raw()
    );
    let c = &b"hiefgabcdjk"[..];
    assert_parse!(
        perm.parse_peek(Partial::new(c)),
        str![[r#"
Ok(
    (
        Partial {
            input: [
                106,
                107,
            ],
            partial: true,
        },
        (
            [
                97,
                98,
                99,
                100,
            ],
            [
                101,
                102,
                103,
            ],
            [
                104,
                105,
            ],
        ),
    ),
)

"#]]
        .raw()
    );

    let d = &b"efgxyzabcdefghi"[..];
    assert_parse!(
        perm.parse_peek(Partial::new(d)),
        str![[r#"
Err(
    Backtrack(
        InputError {
            input: Partial {
                input: [
                    120,
                    121,
                    122,
                    97,
                    98,
                    99,
                    100,
                    101,
                    102,
                    103,
                    104,
                    105,
                ],
                partial: true,
            },
        },
    ),
)

"#]]
        .raw()
    );

    let e = &b"efgabc"[..];
    assert_parse!(
        perm.parse_peek(Partial::new(e)),
        str![[r#"
Err(
    Incomplete(
        Unknown,
    ),
)

"#]]
        .raw()
    );
}
