use chumsky::Parser as ChumskyParser;
use crate::parser::{
close_block, key_value_numeric, open_block, InternalParser, Parser, TokenError, TokenSource,
};
#[derive(Clone, Debug)]
pub struct VersionInfo {
pub editor_version: u32,
pub editor_build: u32,
pub map_version: u16,
pub format_version: u16,
pub prefab: u32,
}
impl VersionInfo {
pub fn new(
version: u32,
build: u32,
map_version: u16,
format_version: u16,
prefab: u32,
) -> VersionInfo {
Self {
editor_version: version,
editor_build: build,
map_version,
format_version,
prefab,
}
}
}
impl Parser<'_> for VersionInfo {}
impl<'src> InternalParser<'src> for VersionInfo {
fn parser<I>() -> impl ChumskyParser<'src, I, Self, TokenError<'src>>
where
I: TokenSource<'src>,
{
open_block("versioninfo")
.ignored()
.then(key_value_numeric::<u32, I>("editorversion"))
.then(key_value_numeric::<u32, I>("editorbuild"))
.then(key_value_numeric::<u16, I>("mapversion"))
.then(key_value_numeric::<u16, I>("formatversion"))
.then(key_value_numeric::<u32, I>("prefab"))
.map(|(((((_, vi), eb), mv), fv), pf)| VersionInfo::new(vi, eb, mv, fv, pf))
.then_ignore(close_block())
.boxed()
}
}
#[cfg(test)]
mod tests {
use crate::util::lex;
use super::*;
use chumsky::Parser;
#[test]
fn test_version_info_parser() {
let input = lex(r#"versioninfo
{
"editorversion" "400"
"editorbuild" "6157"
"mapversion" "16"
"formatversion" "100"
"prefab" "0"
}"#);
let result = VersionInfo::parser().parse(input);
assert!(
!result.has_errors(),
"Parser failed with error: {:?}",
result.errors().collect::<Vec<_>>()
);
let version_info = result.unwrap();
assert_eq!(version_info.editor_version, 400);
assert_eq!(version_info.editor_build, 6157);
assert_eq!(version_info.map_version, 16);
assert_eq!(version_info.format_version, 100);
assert_eq!(version_info.prefab, 0);
let compact_input = lex(
r#"versioninfo{"editorversion""500""editorbuild""7000""mapversion""20""formatversion""110""prefab""1"}"#,
);
let compact_result = VersionInfo::parser().parse(compact_input);
assert!(
!compact_result.has_errors(),
"Compact parser failed with error: {:?}",
compact_result.errors().collect::<Vec<_>>()
);
let missing_field = lex(r#"versioninfo
{
"editorversion" "400"
"editorbuild" "6157"
"mapversion" "16"
"prefab" "0"
}"#);
let missing_result = VersionInfo::parser().parse(missing_field);
assert!(
missing_result.has_errors(),
"Parser should fail on missing field"
);
let invalid_format = lex(r#"versioninfo
{
"editorversion" "400"
"editorbuild" "invalid"
"mapversion" "16"
"formatversion" "100"
"prefab" "0"
}"#);
let invalid_result = VersionInfo::parser().parse(invalid_format);
assert!(
invalid_result.has_errors(),
"Parser should fail on invalid number format"
);
}
}