use token_parser::{ErrorKind, Parser, Span, Unit};
use token_parser_derive::{Parsable, SymbolParsable};
fn symbol(name: &str) -> Unit {
Unit::Symbol(name.into(), Span::default())
}
fn list<I: IntoIterator<Item = Unit>>(items: I) -> Unit {
Unit::Parser(Parser::new(items))
}
fn parse_one<T: token_parser::Parsable<()>>(unit: Unit) -> token_parser::Result<T> {
let mut parser = Parser::new([unit]);
parser.parse_next(&())
}
#[derive(Parsable, Debug, PartialEq)]
struct Pair(String, String);
#[derive(Parsable, Debug, PartialEq, Default)]
struct Config {
label: String,
flag: bool,
}
#[derive(Parsable, Debug, PartialEq)]
struct Empty;
#[derive(SymbolParsable, Debug, PartialEq)]
struct Flag(bool);
#[derive(Parsable, Debug, PartialEq)]
struct Generic<T>(T);
#[test]
fn tuple_struct() {
let result: Pair = parse_one(list([symbol("a"), symbol("b")])).unwrap();
assert_eq!(result, Pair("a".into(), "b".into()));
}
#[test]
fn tuple_struct_missing_element() {
let error = parse_one::<Pair>(list([symbol("a")])).unwrap_err();
assert!(matches!(error.kind, ErrorKind::NotEnoughElements(2)));
assert_eq!(error.context.as_deref(), Some("field 1 of `Pair`"));
}
#[test]
fn named_struct() {
let result: Config = parse_one(list([
list([symbol("flag"), symbol("true")]),
list([symbol("label"), symbol("x")]),
]))
.unwrap();
assert_eq!(
result,
Config {
label: "x".into(),
flag: true,
}
);
}
#[test]
fn named_struct_missing_fields_keep_default() {
let result: Config = parse_one(list([list([symbol("label"), symbol("x")])])).unwrap();
assert_eq!(
result,
Config {
label: "x".into(),
flag: false,
}
);
}
#[test]
fn named_struct_unknown_field() {
let error = parse_one::<Config>(list([list([symbol("bogus"), symbol("x")])])).unwrap_err();
assert!(matches!(error.kind, ErrorKind::UnknownField(name) if name.as_ref() == "bogus"));
}
#[test]
fn named_struct_field_error_context() {
let error = parse_one::<Config>(list([list([symbol("flag"), symbol("maybe")])])).unwrap_err();
assert!(matches!(error.kind, ErrorKind::StringParsing("bool")));
assert_eq!(error.context.as_deref(), Some("field `flag` of `Config`"));
}
#[test]
fn unit_struct() {
let result: Empty = parse_one(list([])).unwrap();
assert_eq!(result, Empty);
}
#[test]
fn symbol_struct() {
let result: Flag = parse_one(symbol("true")).unwrap();
assert_eq!(result, Flag(true));
}
#[test]
fn symbol_struct_invalid() {
let error = parse_one::<Flag>(symbol("maybe")).unwrap_err();
assert!(matches!(error.kind, ErrorKind::StringParsing("bool")));
}
#[test]
fn generic_struct() {
let result: Generic<String> = parse_one(list([symbol("a")])).unwrap();
assert_eq!(result, Generic("a".into()));
}