1use std::collections::HashMap;
2use std::sync::Arc;
6
7use prost::Message;
8
9use crate::error::Result;
10use crate::io::ByteReader;
11
12use super::field_decoder::{self, FieldMetadata};
13use super::field_path::FieldPath;
14
15use boon_proto::proto::{CDemoSendTables, CsvcMsgFlattenedSerializer};
16
17#[derive(Debug, Clone)]
19pub struct FieldType {
20 pub base_type: String,
22 pub pointer: bool,
24 pub generic_type: Option<Box<FieldType>>,
26 pub array_length: Option<usize>,
28 pub count: Option<String>,
30}
31
32#[derive(Debug, Clone)]
34pub struct SerializerField {
35 pub var_type: String,
37 pub var_name: String,
39 pub bit_count: Option<i32>,
41 pub low_value: Option<f32>,
43 pub high_value: Option<f32>,
45 pub encode_flags: Option<i32>,
47 pub field_serializer_name: Option<String>,
49 pub send_node: Option<String>,
51 pub var_encoder: Option<String>,
53 pub field_serializer: Option<Arc<Serializer>>,
55 pub field_type: FieldType,
57 pub metadata: FieldMetadata,
59}
60
61impl SerializerField {
62 pub fn get_child(&self, index: usize) -> Option<&SerializerField> {
64 self.field_serializer
65 .as_ref()
66 .and_then(|s| s.fields.get(index).map(|f| f.as_ref()))
67 }
68
69 pub fn is_dynamic_array(&self) -> bool {
71 self.metadata.is_dynamic_array()
72 }
73}
74
75#[derive(Debug, Clone)]
77pub struct Serializer {
78 pub name: String,
79 pub fields: Vec<Arc<SerializerField>>,
80}
81
82impl Serializer {
83 pub fn resolve_field_key(&self, path: &str) -> Option<u64> {
86 let parts: Vec<&str> = path.split('.').collect();
87 self.resolve_parts(&parts, 0)
88 }
89
90 fn resolve_parts(&self, parts: &[&str], depth: usize) -> Option<u64> {
91 if depth >= parts.len() {
92 return None;
93 }
94
95 for (field_idx, field) in self.fields.iter().enumerate() {
96 let mut field_parts: Vec<&str> = Vec::new();
98 if let Some(ref sn) = field.send_node
99 && !sn.is_empty()
100 {
101 for part in sn.split('.') {
102 field_parts.push(part);
103 }
104 }
105 if !field.var_name.is_empty() {
106 field_parts.push(&field.var_name);
107 }
108
109 let remaining = &parts[depth..];
111 if remaining.len() < field_parts.len() {
112 continue;
113 }
114 if field_parts != remaining[..field_parts.len()] {
115 continue;
116 }
117
118 let consumed = depth + field_parts.len();
119
120 if consumed == parts.len() {
122 let mut fp = FieldPath::default();
123 fp.data[0] = field_idx as u8;
124 return Some(fp.pack());
126 }
127
128 let next_part = parts[consumed];
130
131 if field.is_dynamic_array() {
133 if let Ok(array_idx) = next_part.parse::<usize>()
134 && let Some(ref fs) = field.field_serializer
135 {
136 let inner_field = &fs.fields[0];
137 let after_idx = consumed + 1;
138
139 if after_idx == parts.len() {
140 let mut fp = FieldPath::default();
142 fp.data[0] = field_idx as u8;
143 fp.data[1] = array_idx as u8;
144 fp.last = 1;
145 return Some(fp.pack());
146 }
147
148 if let Some(ref inner_fs) = inner_field.field_serializer
150 && let Some(key) = inner_fs.resolve_parts(parts, after_idx)
151 {
152 let inner_fp = FieldPath::unpack(key);
153 let mut fp = FieldPath::default();
154 fp.data[0] = field_idx as u8;
155 fp.data[1] = array_idx as u8;
156 fp.last = 2 + inner_fp.last;
157 for i in 0..=inner_fp.last {
158 fp.data[2 + i] = inner_fp.data[i];
159 }
160 return Some(fp.pack());
161 }
162 }
163 continue;
164 }
165
166 if let Some(ref fs) = field.field_serializer
168 && let Some(key) = fs.resolve_parts(parts, consumed)
169 {
170 let inner_fp = FieldPath::unpack(key);
171 let mut fp = FieldPath::default();
172 fp.data[0] = field_idx as u8;
173 fp.last = 1 + inner_fp.last;
174 for i in 0..=inner_fp.last {
175 fp.data[1 + i] = inner_fp.data[i];
176 }
177 return Some(fp.pack());
178 }
179 }
180
181 None
182 }
183
184 pub fn field_name_for_key(&self, key: u64) -> Option<String> {
187 let fp = FieldPath::unpack(key);
188 let mut parts: Vec<String> = Vec::new();
189 let mut field = self.fields.get(fp.get(0))?;
190
191 if let Some(ref sn) = field.send_node
192 && !sn.is_empty()
193 {
194 for part in sn.split('.') {
195 parts.push(part.to_string());
196 }
197 }
198 parts.push(field.var_name.clone());
199
200 for i in 1..=fp.last {
201 let idx = fp.get(i);
202 if field.is_dynamic_array() {
203 parts.push(idx.to_string());
204 if let Some(ref fs) = field.field_serializer {
205 field = &fs.fields[0];
206 } else {
207 break;
208 }
209 } else if let Some(ref fs) = field.field_serializer {
210 field = fs.fields.get(idx)?;
211 if let Some(ref sn) = field.send_node
212 && !sn.is_empty()
213 {
214 for part in sn.split('.') {
215 parts.push(part.to_string());
216 }
217 }
218 parts.push(field.var_name.clone());
219 } else {
220 break;
221 }
222 }
223
224 Some(parts.join("."))
225 }
226}
227
228pub struct SerializerContainer {
230 pub serializers: HashMap<String, Arc<Serializer>>,
231}
232
233impl SerializerContainer {
234 pub fn parse(cmd: CDemoSendTables) -> Result<Self> {
236 let data = cmd.data.unwrap_or_default();
237 let mut data_reader = ByteReader::new(&data);
238
239 let _size = data_reader.read_uvarint64()?;
241 let remaining = data_reader.read_bytes(data_reader.remaining())?;
242 let msg = CsvcMsgFlattenedSerializer::decode(remaining)?;
243
244 let symbols = &msg.symbols;
245
246 let resolve_sym = |i: i32| -> &str { &symbols[i as usize] };
247
248 let mut field_cache: HashMap<i32, Arc<SerializerField>> = HashMap::new();
250 let mut serializer_map: HashMap<String, Arc<Serializer>> = HashMap::new();
251
252 for serializer_proto in &msg.serializers {
253 let ser_name = resolve_sym(serializer_proto.serializer_name_sym.unwrap_or(0));
254 let mut serializer = Serializer {
255 name: ser_name.to_string(),
256 fields: Vec::with_capacity(serializer_proto.fields_index.len()),
257 };
258
259 for &field_index in &serializer_proto.fields_index {
260 if let Some(cached) = field_cache.get(&field_index) {
261 serializer.fields.push(cached.clone());
262 continue;
263 }
264
265 let field_proto = &msg.fields[field_index as usize];
266
267 let var_type = field_proto
268 .var_type_sym
269 .map(resolve_sym)
270 .unwrap_or("")
271 .to_string();
272 let var_name = field_proto
273 .var_name_sym
274 .map(resolve_sym)
275 .unwrap_or("")
276 .to_string();
277 let send_node = field_proto.send_node_sym.map(resolve_sym).map(String::from);
278 let var_encoder = field_proto
279 .var_encoder_sym
280 .map(resolve_sym)
281 .map(String::from);
282 let field_serializer_name = field_proto
283 .field_serializer_name_sym
284 .map(resolve_sym)
285 .map(String::from);
286
287 let field_type = parse_type(&var_type);
288 let metadata = field_decoder::get_field_metadata(
289 &var_type,
290 &var_name,
291 field_proto.bit_count,
292 field_proto.low_value,
293 field_proto.high_value,
294 field_proto.encode_flags,
295 var_encoder.as_deref(),
296 field_serializer_name.is_some(),
297 );
298
299 let field_serializer = match &metadata {
301 fm if fm.is_fixed_array() => {
302 let length = fm.fixed_array_length().unwrap_or(0);
303 let inner_ser = field_serializer_name
305 .as_deref()
306 .and_then(|n| serializer_map.get(n).cloned());
307
308 let inner_field = SerializerField {
309 var_type: var_type.clone(),
310 var_name: var_name.clone(),
311 bit_count: field_proto.bit_count,
312 low_value: field_proto.low_value,
313 high_value: field_proto.high_value,
314 encode_flags: field_proto.encode_flags,
315 field_serializer_name: field_serializer_name.clone(),
316 send_node: send_node.clone(),
317 var_encoder: var_encoder.clone(),
318 field_serializer: inner_ser,
319 field_type: field_type.clone(),
320 metadata: metadata.clone(),
321 };
322 let inner_rc = Arc::new(inner_field);
323 let mut fields = Vec::with_capacity(length);
324 fields.resize(length, inner_rc);
325 Some(Arc::new(Serializer {
326 name: String::new(),
327 fields,
328 }))
329 }
330 fm if fm.is_dynamic_array() => {
331 if fm.is_dynamic_serializer_array() {
333 let inner_ser = field_serializer_name
334 .as_deref()
335 .and_then(|n| serializer_map.get(n).cloned());
336 let inner = Arc::new(SerializerField {
337 var_type: String::new(),
338 var_name: String::new(),
339 bit_count: None,
340 low_value: None,
341 high_value: None,
342 encode_flags: None,
343 field_serializer_name: None,
344 send_node: None,
345 var_encoder: None,
346 field_serializer: inner_ser,
347 field_type: parse_type(""),
348 metadata: FieldMetadata::default(),
349 });
350 Some(Arc::new(Serializer {
351 name: String::new(),
352 fields: vec![inner],
353 }))
354 } else {
355 let inner_metadata = fm.dynamic_array_inner_metadata();
357 let inner = Arc::new(SerializerField {
358 var_type: String::new(),
359 var_name: String::new(),
360 bit_count: None,
361 low_value: None,
362 high_value: None,
363 encode_flags: None,
364 field_serializer_name: None,
365 send_node: None,
366 var_encoder: None,
367 field_serializer: None,
368 field_type: parse_type(""),
369 metadata: inner_metadata,
370 });
371 Some(Arc::new(Serializer {
372 name: String::new(),
373 fields: vec![inner],
374 }))
375 }
376 }
377 fm if fm.is_pointer() => field_serializer_name
378 .as_deref()
379 .and_then(|n| serializer_map.get(n).cloned()),
380 _ => field_serializer_name
381 .as_deref()
382 .and_then(|n| serializer_map.get(n).cloned()),
383 };
384
385 let field = Arc::new(SerializerField {
386 var_type,
387 var_name,
388 bit_count: field_proto.bit_count,
389 low_value: field_proto.low_value,
390 high_value: field_proto.high_value,
391 encode_flags: field_proto.encode_flags,
392 field_serializer_name,
393 send_node,
394 var_encoder,
395 field_serializer,
396 field_type,
397 metadata,
398 });
399
400 field_cache.insert(field_index, field.clone());
401 serializer.fields.push(field);
402 }
403
404 serializer_map.insert(serializer.name.clone(), Arc::new(serializer));
405 }
406
407 Ok(Self {
408 serializers: serializer_map,
409 })
410 }
411
412 pub fn get(&self, name: &str) -> Option<&Serializer> {
414 self.serializers.get(name).map(|arc| arc.as_ref())
415 }
416}
417
418pub fn parse_type(s: &str) -> FieldType {
420 let s = s.trim();
421
422 if let Some(stripped) = s.strip_suffix('*') {
424 return FieldType {
425 base_type: stripped.trim().to_string(),
426 pointer: true,
427 generic_type: None,
428 array_length: None,
429 count: None,
430 };
431 }
432
433 if let Some(bracket_pos) = s.find('[')
435 && s.ends_with(']')
436 {
437 let base = s[..bracket_pos].trim();
438 let len_str = s[bracket_pos + 1..s.len() - 1].trim();
439 let array_length = len_str.parse::<usize>().ok();
440 let count = if array_length.is_none() {
441 Some(len_str.to_string())
442 } else {
443 None
444 };
445 return FieldType {
446 base_type: base.to_string(),
447 pointer: false,
448 generic_type: None,
449 array_length,
450 count,
451 };
452 }
453
454 if let Some(angle_pos) = s.find('<')
456 && let Some(close_pos) = s.rfind('>')
457 {
458 let base = s[..angle_pos].trim();
459 let inner = s[angle_pos + 1..close_pos].trim();
460 return FieldType {
461 base_type: base.to_string(),
462 pointer: false,
463 generic_type: Some(Box::new(parse_type(inner))),
464 array_length: None,
465 count: None,
466 };
467 }
468
469 FieldType {
471 base_type: s.to_string(),
472 pointer: false,
473 generic_type: None,
474 array_length: None,
475 count: None,
476 }
477}
478
479#[cfg(test)]
480mod tests {
481 use super::super::field_decoder::{Decoder, FieldMetadata};
482 use super::*;
483
484 #[test]
487 fn parse_type_simple() {
488 let ft = parse_type("int32");
489 assert_eq!(ft.base_type, "int32");
490 assert!(!ft.pointer);
491 assert!(ft.generic_type.is_none());
492 assert!(ft.array_length.is_none());
493 assert!(ft.count.is_none());
494 }
495
496 #[test]
497 fn parse_type_pointer() {
498 let ft = parse_type("CBaseEntity*");
499 assert_eq!(ft.base_type, "CBaseEntity");
500 assert!(ft.pointer);
501 }
502
503 #[test]
504 fn parse_type_array_numeric() {
505 let ft = parse_type("int32[4]");
506 assert_eq!(ft.base_type, "int32");
507 assert_eq!(ft.array_length, Some(4));
508 assert!(ft.count.is_none());
509 }
510
511 #[test]
512 fn parse_type_array_symbolic() {
513 let ft = parse_type("int32[MAX_ABILITIES]");
514 assert_eq!(ft.base_type, "int32");
515 assert!(ft.array_length.is_none());
516 assert_eq!(ft.count.as_deref(), Some("MAX_ABILITIES"));
517 }
518
519 #[test]
520 fn parse_type_generic() {
521 let ft = parse_type("CNetworkUtlVectorBase< int32 >");
522 assert_eq!(ft.base_type, "CNetworkUtlVectorBase");
523 let inner = ft.generic_type.as_ref().unwrap();
524 assert_eq!(inner.base_type, "int32");
525 }
526
527 #[test]
528 fn parse_type_generic_nested() {
529 let ft = parse_type("CHandle< CBaseEntity >");
530 assert_eq!(ft.base_type, "CHandle");
531 assert_eq!(ft.generic_type.as_ref().unwrap().base_type, "CBaseEntity");
532 }
533
534 #[test]
535 fn parse_type_whitespace_trimming() {
536 let ft = parse_type(" float32 ");
537 assert_eq!(ft.base_type, "float32");
538 }
539
540 #[test]
541 fn parse_type_empty_string() {
542 let ft = parse_type("");
543 assert_eq!(ft.base_type, "");
544 assert!(!ft.pointer);
545 }
546
547 #[test]
548 fn parse_type_complex_all_fields() {
549 let ft = parse_type("uint32[16]");
550 assert_eq!(ft.base_type, "uint32");
551 assert!(!ft.pointer);
552 assert!(ft.generic_type.is_none());
553 assert_eq!(ft.array_length, Some(16));
554 assert!(ft.count.is_none());
555 }
556
557 fn make_field(name: &str, send_node: Option<&str>) -> Arc<SerializerField> {
560 Arc::new(SerializerField {
561 var_type: String::new(),
562 var_name: name.to_string(),
563 bit_count: None,
564 low_value: None,
565 high_value: None,
566 encode_flags: None,
567 field_serializer_name: None,
568 send_node: send_node.map(String::from),
569 var_encoder: None,
570 field_serializer: None,
571 field_type: parse_type(""),
572 metadata: FieldMetadata {
573 decoder: Decoder::U64,
574 special: None,
575 },
576 })
577 }
578
579 #[test]
580 fn resolve_field_key_found() {
581 let ser = Serializer {
582 name: "test".to_string(),
583 fields: vec![make_field("m_iHealth", None)],
584 };
585 assert!(ser.resolve_field_key("m_iHealth").is_some());
586 }
587
588 #[test]
589 fn resolve_field_key_not_found() {
590 let ser = Serializer {
591 name: "test".to_string(),
592 fields: vec![make_field("m_iHealth", None)],
593 };
594 assert!(ser.resolve_field_key("m_iMana").is_none());
595 }
596
597 #[test]
598 fn field_name_roundtrip() {
599 let ser = Serializer {
600 name: "test".to_string(),
601 fields: vec![make_field("m_iHealth", None), make_field("m_iMana", None)],
602 };
603 let key = ser.resolve_field_key("m_iMana").unwrap();
604 let name = ser.field_name_for_key(key).unwrap();
605 assert_eq!(name, "m_iMana");
606 }
607
608 #[test]
609 fn resolve_with_send_node() {
610 let ser = Serializer {
611 name: "test".to_string(),
612 fields: vec![make_field("m_bPaused", Some("m_pGameRules"))],
613 };
614 let key = ser.resolve_field_key("m_pGameRules.m_bPaused");
615 assert!(key.is_some());
616 let name = ser.field_name_for_key(key.unwrap()).unwrap();
617 assert_eq!(name, "m_pGameRules.m_bPaused");
618 }
619}