source_demo_tool/demo_file/
header.rs1use std::io::Read;
2use crate::parse_tools:: {
3 parse_f32,
4 parse_i32,
5 parse_fixed_width_string
6};
7
8#[derive(Debug, Clone)]
9pub struct DemoHeader {
10 pub demo_protocol: i32,
11 pub network_protocol: i32,
12 pub server_name: String,
13 pub client_name: String,
14 pub map_name: String,
15 pub game_directory: String,
16 pub playback_time: f32,
17 pub ticks: i32,
18 pub frames: i32,
19 pub sign_on_length: i32,
20}
21
22impl DemoHeader {
23 pub fn from_readable(mut reader: impl Read) -> Result<DemoHeader, String> {
24 let mut buffer: [u8; 8] = [0; 8];
26 match reader.read_exact(&mut buffer) {
27 Ok(()) => match String::from_utf8(buffer.to_vec()) {
28 Ok(str) => {
29 if str != "HL2DEMO\0" {
30 return Err(String::from("file magic header != HL2DEMO"))
31 }
32 },
33 Err(_) => return Err(String::from("couldn't parse header string"))
34 },
35 Err(_) => return Err(String::from("couldn't read header string"))
36 }
37
38 let demo_protocol = match parse_i32(&mut reader) {
40 Ok(n) => {
41 if n < 0 {
42 return Err(String::from("unexpected negative demo protocol"))
43 }
44 n
45 }
46 Err(e) => return Err(format!("error parsing demo protocol: {e}"))
47 };
48
49 let network_protocol = match parse_i32(&mut reader) {
51 Ok(n) => {
52 if n < 0 {
53 return Err(String::from("unexpected negative network protocol"))
54 }
55 n
56 }
57 Err(e) => return Err(format!("error parsing network protocol: {e}"))
58 };
59
60 let server_name = match parse_fixed_width_string(&mut reader, 260) {
62 Ok(s) => s,
63 Err(e) => return Err(format!("error parsing server name: {e}"))
64 };
65
66 let client_name = match parse_fixed_width_string(&mut reader, 260) {
68 Ok(s) => s,
69 Err(e) => return Err(format!("error parsing client name: {e}"))
70 };
71
72 let map_name = match parse_fixed_width_string(&mut reader, 260) {
74 Ok(s) => s,
75 Err(e) => return Err(format!("error parsing map name: {e}"))
76 };
77
78 let game_directory = match parse_fixed_width_string(&mut reader, 260) {
80 Ok(s) => s,
81 Err(e) => return Err(format!("error parsing game directory: {e}"))
82 };
83
84 let playback_time = match parse_f32(&mut reader) {
86 Ok(n) => {
87 if n < 0.0 {
88 return Err(String::from("unexpected negative playback time"))
89 }
90 n
91 },
92 Err(e) => return Err(format!("error parsing playback time: {e}"))
93 };
94
95 let ticks = match parse_i32(&mut reader) {
97 Ok(n) => {
98 if n < 0 {
99 return Err(String::from("unexpected negative ticks"))
100 }
101 n
102 },
103 Err(e) => return Err(format!("error parsing ticks: {e}"))
104 };
105
106 let frames = match parse_i32(&mut reader) {
108 Ok(n) => {
109 if n < 0 {
110 return Err(String::from("unexpected negative frames"))
111 }
112 n
113 },
114 Err(e) => return Err(format!("error parsing frames: {e}"))
115 };
116
117 let sign_on_length = match parse_i32(&mut reader) {
119 Ok(n) => {
120 if n < 0 {
121 return Err(String::from("unexpected negative sign on length"))
122 }
123 n
124 }
125 Err(e) => return Err(format!("error parsing sign on length: {e}"))
126 };
127
128 Ok(DemoHeader {
129 demo_protocol,
130 network_protocol,
131 server_name,
132 client_name,
133 map_name,
134 game_directory,
135 playback_time,
136 ticks,
137 frames,
138 sign_on_length
139 })
140 }
141}