paramdex_rs/deserialize/
field_def_parse.rs1use std::str::FromStr;
2use pest_derive::Parser;
3
4#[derive(Parser)]
5#[grammar = "deserialize/fielddef.pest"]
6struct DefParser;
7
8use pest::iterators::Pairs;
9use pest::{Parser, Span};
10use crate::{ParamFieldDef, ParamFieldType};
11
12fn tokenize(input: &str) -> Result<Pairs<Rule>, DefParseError> {
13 DefParser::parse(Rule::def, input.as_ref()).map_err(|a| a.into())
14}
15
16#[derive(Debug)]
17pub struct ErrSpan {
18 pub start: usize,
19 pub end: usize,
20}
21
22#[derive(Error, Debug)]
23pub enum DefParseError {
24 #[error("Failed to parse def line")]
25 ParseError(#[from] pest::error::Error<Rule>),
26
27 #[error("Bit size not supported on this type")]
28 BitSizeUnsupported(ErrSpan),
29}
30
31use thiserror::Error;
32
33pub fn parse_param_field_def<S: AsRef<str>>(input_str: S) -> Result<ParamFieldDef, DefParseError> {
34 let tokenized = tokenize(input_str.as_ref())?.next().expect("First pair");
35 if let Rule::def = tokenized.as_rule() {
36 let inner = tokenized.into_inner().next().expect("def type pair");
37 match inner.as_rule() {
38 Rule::def_simple => {
39 let mut inner = inner.into_inner();
40 let simple_field_type = inner.next().expect("getting simple field type");
41
42 let field_type = match simple_field_type.as_str() {
43 "s8" => ParamFieldType::s8,
44 "u8" => ParamFieldType::u8 { bit_size: None },
45 "s16" => ParamFieldType::s16,
46 "u16" => ParamFieldType::u16 { bit_size: None },
47 "s32" => ParamFieldType::s32,
48 "u32" => ParamFieldType::u32 { bit_size: None },
49 "f32" => ParamFieldType::f32,
50 "f64" => ParamFieldType::f64,
51 "a32" | "angle32" => ParamFieldType::a32,
52 "b32" => ParamFieldType::b32,
53 _ => unreachable!()
54 };
55
56 let field_name = {
57 let inner = inner.next().expect("getting field name");
58 inner.as_str().to_owned()
59 };
60 let mut compiled_field_def = ParamFieldDef {
61 field_type,
62 name: field_name,
63 default_value: None,
64 };
65
66 for suffix in inner {
67 match suffix.as_rule() {
68 Rule::suffix_bitsize => {
69 let span = suffix.as_span();
70 let number = suffix.into_inner().next().expect("number");
71 let bit_size = u8::from_str(number.as_str()).expect("number_str to u8");
72 if compiled_field_def.field_type.supports_bit_size() {
73 compiled_field_def.field_type.set_bit_size(bit_size);
74 } else {
75 return Err(DefParseError::BitSizeUnsupported(span.into()).into());
76 }
77 }
78 Rule::def_default_suffix => {
79 let default_inner = suffix.into_inner().next().expect("default inner");
80 let default_val = f64::from_str(default_inner.as_str()).expect("default str to f64");
81 compiled_field_def.default_value.replace(default_val);
82 }
83 _ => unreachable!()
84 }
85 }
86 Ok(compiled_field_def)
87 }
88 Rule::def_dummy => {
89 unimplemented!()
90 }
91 _ => {
92 unimplemented!()
93 }
94 }
95 } else {
96 unreachable!()
97 }
98}
99
100impl<'i> From<Span<'i>> for ErrSpan {
101 fn from(span: Span<'i>) -> Self {
102 ErrSpan { start: span.start(), end: span.end() }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use std::collections::HashMap;
109 use std::fs::{File};
110 use std::io::{BufReader, Read};
111 use crate::{ParamFieldDef, ParamFieldType};
112 use crate::deserialize::field_def_parse::parse_param_field_def;
113
114 impl PartialEq for ParamFieldDef {
115 fn eq(&self, other: &Self) -> bool {
116 self.field_type == other.field_type && self.default_value == other.default_value && self.name == other.name
117 }
118 }
119
120 #[test]
121 fn simple() {
122 assert_eq!(
123 parse_param_field_def("u32 testingVar").expect("parses"),
124 ParamFieldDef {
125 name: "testingVar".to_string(),
126 default_value: None,
127 field_type: ParamFieldType::u32 { bit_size: None },
128 }
129 )
130 }
131
132 #[test]
133 fn simple_s() {
134 assert_eq!(
135 parse_param_field_def("s32 testingVar2").expect("parses"),
136 ParamFieldDef {
137 name: "testingVar2".to_string(),
138 default_value: None,
139 field_type: ParamFieldType::s32,
140 }
141 )
142 }
143
144 #[test]
145 fn simple_f() {
146 assert_eq!(
147 parse_param_field_def("f32 gradFactor").expect("parses"),
148 ParamFieldDef {
149 name: "gradFactor".to_string(),
150 default_value: None,
151 field_type: ParamFieldType::f32,
152 }
153 )
154 }
155
156 #[test]
157 fn simple_bitsize() {
158 assert_eq!(
159 parse_param_field_def("u32 testingVar:3").expect("parses"),
160 ParamFieldDef {
161 name: "testingVar".to_string(),
162 default_value: None,
163 field_type: ParamFieldType::u32 { bit_size: Some(3) },
164 }
165 )
166 }
167
168 #[test]
169 #[should_panic]
170 fn simple_bitsize_s() {
171 parse_param_field_def("s32 testingVar:3").expect("parses");
172 }
173
174 #[test]
175 fn simple_default() {
176 assert_eq!(
177 parse_param_field_def("u32 testingVar = -3.0").expect("parses"),
178 ParamFieldDef {
179 name: "testingVar".to_string(),
180 default_value: Some(-3.0),
181 field_type: ParamFieldType::u32 { bit_size: None },
182 }
183 )
184 }
185
186 #[test]
187 fn simple_default_s() {
188 assert_eq!(
189 parse_param_field_def("s32 testingVar3 = -3.0").expect("parses"),
190 ParamFieldDef {
191 name: "testingVar3".to_string(),
192 default_value: Some(-3.0),
193 field_type: ParamFieldType::s32,
194 }
195 )
196 }
197
198 #[test]
199 fn simple_default_bitsize() {
200 assert_eq!(
201 parse_param_field_def("u32 testingVar:3 = 0").expect("parses"),
202 ParamFieldDef {
203 name: "testingVar".to_string(),
204 default_value: Some(0.0),
205 field_type: ParamFieldType::u32 { bit_size: Some(3) },
206 }
207 )
208 }
209
210 #[test]
211 #[should_panic]
212 fn simple_default_bitsize_s() {
213 parse_param_field_def("s32 testingVar:3 = 0").expect("parses");
214 }
215
216 #[test]
217 fn test_all_xmls() {
218 let mut errors = HashMap::new();
219 let walkdir = walkdir::WalkDir::new("Paramdex/ER")
220 .into_iter()
221 .filter_map(|a| a.ok())
222 .filter(|a| a.file_type().is_file())
223 .map(|a| a.into_path())
224 .filter(|a| a.extension().map(|a| a == "xml").unwrap_or(false));
225 for a in walkdir {
226 let path = a.to_str().expect("tostr");
227 let string =
228 {
229 let mut string = String::with_capacity(25000);
230 BufReader::new(File::open(&a).expect("opening file"))
231 .read_to_string(&mut string).expect("reading file");
232 string
233 };
234 let doc = roxmltree::Document::parse(string.as_str()).expect("parsing xml");
235 for def_str in doc.descendants().filter(|a| a.has_tag_name("Field")).map(|a| a.attribute("Def").expect("def")) {
236 if !(def_str.contains("fixstr") || def_str.contains("dummy")) {
237 match parse_param_field_def(def_str) {
238 Err(_err) => {
239 if !errors.contains_key(path) {
240 errors.insert(path.to_owned(), Vec::new());
241 }
242 errors.get_mut(path).expect("wewe").push(def_str.to_owned());
243 },
244 _ => {}
245 }
246
247 } else if def_str.contains("fixstrW") {
248 }
250 }
251 }
252
253 for (k,v) in errors {
254 println!("{}", k);
255 for def in v {
256 println!("\t{}", def);
257 }
258 }
259
260 }
261}