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