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