tf_demo_parser/demo/message/
classinfo.rs

1use bitbuffer::{BitRead, BitReadSized, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
2use serde::{Deserialize, Serialize};
3
4use crate::demo::message::stringtable::log_base2;
5use crate::{ReadResult, Stream};
6use std::cmp::min;
7
8#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
9#[derive(BitReadSized, BitWriteSized, Debug, PartialEq, Serialize, Deserialize, Clone)]
10pub struct ClassInfoEntry {
11    #[size = "input_size"]
12    class_id: u16,
13    class_name: String,
14    table_name: String,
15}
16
17#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
18#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
19pub struct ClassInfoMessage {
20    count: u16,
21    create: bool,
22    entries: Vec<ClassInfoEntry>,
23}
24
25impl BitRead<'_, LittleEndian> for ClassInfoMessage {
26    fn read(stream: &mut Stream) -> ReadResult<Self> {
27        let count: u16 = stream.read()?;
28        let create: bool = stream.read()?;
29        let entries = if !create {
30            let mut entries = Vec::with_capacity(min(count, 128) as usize);
31            let bits = log_base2(count) + 1;
32            for _ in 0..count {
33                entries.push(stream.read_sized(bits as usize)?);
34            }
35            entries
36        } else {
37            Vec::new()
38        };
39
40        Ok(ClassInfoMessage {
41            count,
42            create,
43            entries,
44        })
45    }
46}
47
48impl BitWrite<LittleEndian> for ClassInfoMessage {
49    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
50        self.count.write(stream)?;
51        self.create.write(stream)?;
52        if !self.create {
53            let bits = log_base2(self.entries.len()) as usize + 1;
54            for entry in self.entries.iter() {
55                entry.write_sized(stream, bits)?;
56            }
57        }
58
59        Ok(())
60    }
61}
62
63#[test]
64fn test_class_info_roundtrip() {
65    crate::test_roundtrip_write(ClassInfoMessage {
66        count: 8,
67        create: true,
68        entries: Vec::new(),
69    });
70    crate::test_roundtrip_write(ClassInfoMessage {
71        count: 3,
72        create: false,
73        entries: vec![
74            ClassInfoEntry {
75                class_id: 0,
76                class_name: "foo1".to_string(),
77                table_name: "bar1".to_string(),
78            },
79            ClassInfoEntry {
80                class_id: 1,
81                class_name: "foo2".to_string(),
82                table_name: "bar2".to_string(),
83            },
84            ClassInfoEntry {
85                class_id: 2,
86                class_name: "foo3".to_string(),
87                table_name: "bar3".to_string(),
88            },
89        ],
90    });
91}