tf_demo_parser/demo/data/
mod.rs

1pub mod userinfo;
2
3use bitbuffer::{BitRead, BitReadStream, BitWrite, BitWriteStream, Endianness};
4use parse_display::Display;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::cmp::Ordering;
7use std::fmt::{Debug, Display, Formatter};
8use std::ops::{Add, Sub};
9
10pub use userinfo::UserInfo;
11
12#[derive(Eq, PartialEq, Clone)]
13pub enum MaybeUtf8String {
14    Valid(String),
15    Invalid(Vec<u8>),
16}
17
18impl From<&'_ str> for MaybeUtf8String {
19    fn from(str: &'_ str) -> Self {
20        MaybeUtf8String::Valid(str.into())
21    }
22}
23
24impl Default for MaybeUtf8String {
25    fn default() -> Self {
26        MaybeUtf8String::Valid(String::new())
27    }
28}
29
30impl AsRef<str> for MaybeUtf8String {
31    fn as_ref(&self) -> &str {
32        match self {
33            MaybeUtf8String::Valid(s) => s.as_str(),
34            MaybeUtf8String::Invalid(_) => "-- Malformed utf8 --",
35        }
36    }
37}
38
39impl Debug for MaybeUtf8String {
40    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41        match self {
42            MaybeUtf8String::Valid(s) => Debug::fmt(s, f),
43            MaybeUtf8String::Invalid(b) => f
44                .debug_struct("MaybeUtf8String::Invalid")
45                .field("data", b)
46                .finish(),
47        }
48    }
49}
50
51impl Display for MaybeUtf8String {
52    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53        match self {
54            MaybeUtf8String::Valid(s) => Display::fmt(s, f),
55            MaybeUtf8String::Invalid(_) => write!(f, "-- Malformed utf8 --"),
56        }
57    }
58}
59
60impl MaybeUtf8String {
61    pub fn as_bytes(&self) -> &[u8] {
62        match self {
63            MaybeUtf8String::Valid(s) => s.as_bytes(),
64            MaybeUtf8String::Invalid(b) => b.as_ref(),
65        }
66    }
67}
68
69impl<'a, E: Endianness> BitRead<'a, E> for MaybeUtf8String {
70    fn read(stream: &mut BitReadStream<'a, E>) -> bitbuffer::Result<Self> {
71        match String::read(stream) {
72            Ok(str) => Ok(MaybeUtf8String::Valid(str)),
73            Err(bitbuffer::BitError::Utf8Error(_, size)) => {
74                stream.set_pos(stream.pos().saturating_sub(size * 8))?;
75                let mut data: Vec<u8> = stream.read_sized(size)?;
76                while data.last() == Some(&0) {
77                    data.pop();
78                }
79                match String::from_utf8(data) {
80                    Ok(str) => Ok(MaybeUtf8String::Valid(str)),
81                    Err(e) => Ok(MaybeUtf8String::Invalid(e.into_bytes())),
82                }
83            }
84            Err(e) => Err(e),
85        }
86    }
87}
88
89impl<E: Endianness> BitWrite<E> for MaybeUtf8String {
90    fn write(&self, stream: &mut BitWriteStream<E>) -> bitbuffer::Result<()> {
91        stream.write_bytes(self.as_bytes())?;
92        stream.write(&0u8)
93    }
94}
95
96impl From<MaybeUtf8String> for String {
97    fn from(str: MaybeUtf8String) -> String {
98        match str {
99            MaybeUtf8String::Valid(s) => s,
100            MaybeUtf8String::Invalid(_) => "-- Malformed utf8 --".into(),
101        }
102    }
103}
104
105impl Serialize for MaybeUtf8String {
106    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107    where
108        S: Serializer,
109    {
110        self.as_ref().serialize(serializer)
111    }
112}
113
114impl<'de> Deserialize<'de> for MaybeUtf8String {
115    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
116    where
117        D: Deserializer<'de>,
118    {
119        String::deserialize(deserializer).map(MaybeUtf8String::Valid)
120    }
121}
122
123#[cfg(feature = "schema")]
124impl schemars::JsonSchema for MaybeUtf8String {
125    fn schema_name() -> String {
126        String::schema_name()
127    }
128
129    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
130        String::json_schema(gen)
131    }
132}
133
134/// Tick relative to the start of the game on the server
135#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
136#[derive(
137    Debug,
138    Clone,
139    Copy,
140    Ord,
141    PartialOrd,
142    Eq,
143    PartialEq,
144    BitRead,
145    BitWrite,
146    Serialize,
147    Deserialize,
148    Default,
149    Display,
150)]
151pub struct ServerTick(u32);
152
153impl ServerTick {
154    pub fn range_inclusive(&self, till: Self) -> impl Iterator<Item = Self> {
155        (self.0..=till.0).map(Self::from)
156    }
157}
158
159impl PartialEq<u32> for ServerTick {
160    fn eq(&self, other: &u32) -> bool {
161        *other == self.0
162    }
163}
164
165impl PartialOrd<u32> for ServerTick {
166    fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
167        self.0.partial_cmp(other)
168    }
169}
170
171impl PartialEq<ServerTick> for u32 {
172    fn eq(&self, other: &ServerTick) -> bool {
173        self.eq(&other.0)
174    }
175}
176
177impl PartialOrd<ServerTick> for u32 {
178    fn partial_cmp(&self, other: &ServerTick) -> Option<Ordering> {
179        self.partial_cmp(&other.0)
180    }
181}
182
183impl From<u32> for ServerTick {
184    fn from(tick: u32) -> Self {
185        ServerTick(tick)
186    }
187}
188
189impl From<ServerTick> for u32 {
190    fn from(tick: ServerTick) -> Self {
191        tick.0
192    }
193}
194
195impl Add<u32> for ServerTick {
196    type Output = ServerTick;
197
198    fn add(self, rhs: u32) -> Self::Output {
199        ServerTick(self.0 + rhs)
200    }
201}
202
203impl Add<ServerTick> for ServerTick {
204    type Output = ServerTick;
205
206    fn add(self, rhs: ServerTick) -> Self::Output {
207        ServerTick(self.0 + rhs.0)
208    }
209}
210
211impl Sub<u32> for ServerTick {
212    type Output = ServerTick;
213
214    fn sub(self, rhs: u32) -> Self::Output {
215        ServerTick(self.0 - rhs)
216    }
217}
218
219impl Sub<ServerTick> for ServerTick {
220    type Output = ServerTick;
221
222    fn sub(self, rhs: ServerTick) -> Self::Output {
223        ServerTick(self.0 - rhs.0)
224    }
225}
226
227/// Tick relative to the start of the demo
228#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
229#[derive(
230    Debug,
231    Clone,
232    Copy,
233    Ord,
234    PartialOrd,
235    Eq,
236    PartialEq,
237    BitRead,
238    BitWrite,
239    Serialize,
240    Deserialize,
241    Default,
242    Display,
243)]
244pub struct DemoTick(u32);
245
246impl DemoTick {
247    pub fn range_inclusive(&self, till: Self) -> impl Iterator<Item = Self> {
248        (self.0..=till.0).map(Self::from)
249    }
250}
251
252impl PartialEq<u32> for DemoTick {
253    fn eq(&self, other: &u32) -> bool {
254        *other == self.0
255    }
256}
257
258impl PartialOrd<u32> for DemoTick {
259    fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
260        self.0.partial_cmp(other)
261    }
262}
263
264impl PartialEq<DemoTick> for u32 {
265    fn eq(&self, other: &DemoTick) -> bool {
266        self.eq(&other.0)
267    }
268}
269
270impl PartialOrd<DemoTick> for u32 {
271    fn partial_cmp(&self, other: &DemoTick) -> Option<Ordering> {
272        self.partial_cmp(&other.0)
273    }
274}
275
276impl From<u32> for DemoTick {
277    fn from(tick: u32) -> Self {
278        DemoTick(tick)
279    }
280}
281
282impl From<DemoTick> for u32 {
283    fn from(tick: DemoTick) -> Self {
284        tick.0
285    }
286}
287
288impl Add<u32> for DemoTick {
289    type Output = DemoTick;
290
291    fn add(self, rhs: u32) -> Self::Output {
292        DemoTick(self.0 + rhs)
293    }
294}
295
296impl Add<DemoTick> for DemoTick {
297    type Output = DemoTick;
298
299    fn add(self, rhs: DemoTick) -> Self::Output {
300        DemoTick(self.0 + rhs.0)
301    }
302}
303
304impl Sub<u32> for DemoTick {
305    type Output = DemoTick;
306
307    fn sub(self, rhs: u32) -> Self::Output {
308        DemoTick(self.0 - rhs)
309    }
310}
311
312impl Sub<DemoTick> for DemoTick {
313    type Output = DemoTick;
314
315    fn sub(self, rhs: DemoTick) -> Self::Output {
316        DemoTick(self.0 - rhs.0)
317    }
318}