tf_demo_parser/demo/message/
voice.rs

1use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
2use serde::{Deserialize, Serialize};
3
4use crate::{ReadResult, Stream};
5
6#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct VoiceInitMessage {
9    pub codec: String,
10    pub quality: u8,
11    pub sampling_rate: u16,
12}
13
14impl BitRead<'_, LittleEndian> for VoiceInitMessage {
15    fn read(stream: &mut Stream) -> ReadResult<Self> {
16        let codec = stream.read()?;
17        let quality = stream.read()?;
18
19        let sampling_rate = if quality == 255 {
20            // v2 packets have variable rate
21            stream.read()?
22        } else if codec == "vaudio_celt" {
23            // legacy sample rate for celt
24            22050
25        } else {
26            // legacy sample rate for non-celt
27            11025
28        };
29
30        Ok(VoiceInitMessage {
31            codec,
32            quality,
33            sampling_rate,
34        })
35    }
36}
37
38impl BitWrite<LittleEndian> for VoiceInitMessage {
39    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
40        self.codec.write(stream)?;
41        self.quality.write(stream)?;
42
43        if self.quality == 255 {
44            self.sampling_rate.write(stream)?;
45        }
46
47        Ok(())
48    }
49}
50
51#[test]
52fn test_voice_init_roundtrip() {
53    crate::test_roundtrip_write(VoiceInitMessage {
54        codec: "foo".into(),
55        quality: 0,
56        sampling_rate: 11025,
57    });
58    crate::test_roundtrip_write(VoiceInitMessage {
59        codec: "foo".into(),
60        quality: 255,
61        sampling_rate: 12,
62    });
63}
64
65#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
66#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
67#[endianness = "LittleEndian"]
68#[serde(bound(deserialize = "'a: 'static"))]
69pub struct VoiceDataMessage<'a> {
70    pub client: u8,
71    pub proximity: u8,
72    pub length: u16,
73    #[size = "length"]
74    pub data: Stream<'a>,
75}
76
77#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
78#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79#[serde(bound(deserialize = "'a: 'static"))]
80pub struct ParseSoundsMessage<'a> {
81    pub reliable: bool,
82    pub num: u8,
83    pub length: u16,
84    pub data: Stream<'a>,
85}
86
87impl<'a> BitRead<'a, LittleEndian> for ParseSoundsMessage<'a> {
88    fn read(stream: &mut Stream<'a>) -> ReadResult<Self> {
89        let reliable = stream.read()?;
90        let num = if reliable { 1u8 } else { stream.read()? };
91        let length = if reliable {
92            stream.read_sized::<u16>(8)?
93        } else {
94            stream.read()?
95        };
96        let data = stream.read_sized(length as usize)?;
97
98        Ok(ParseSoundsMessage {
99            reliable,
100            num,
101            length,
102            data,
103        })
104    }
105}
106
107impl BitWrite<LittleEndian> for ParseSoundsMessage<'_> {
108    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
109        self.reliable.write(stream)?;
110        if !self.reliable {
111            self.num.write(stream)?;
112        }
113
114        if self.reliable {
115            self.length.write_sized(stream, 8)?;
116        } else {
117            self.length.write(stream)?;
118        }
119
120        self.data.write(stream)?;
121
122        Ok(())
123    }
124}
125
126#[test]
127fn test_parse_sounds_roundtrip() {
128    use bitbuffer::BitReadBuffer;
129    let inner = BitReadBuffer::new(&[1, 2, 3, 4, 5, 6], LittleEndian);
130
131    crate::test_roundtrip_write(ParseSoundsMessage {
132        reliable: false,
133        num: 0,
134        length: inner.bit_len() as u16,
135        data: inner.clone().into(),
136    });
137    crate::test_roundtrip_write(ParseSoundsMessage {
138        reliable: true,
139        num: 1,
140        length: inner.bit_len() as u16,
141        data: inner.into(),
142    });
143}