1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
pub use quake_serverinfo::Serverinfo;

use crate::util;

pub fn serverinfo(data: &[u8]) -> Option<Serverinfo> {
    serverinfo_string(data).map(|str| Serverinfo::from(str.as_str()))
}

pub fn serverinfo_string(data: &[u8]) -> Option<String> {
    let (from, to) = util::offsets_between(data, br#"fullserverinfo ""#, br#"""#)?;
    String::from_utf8(data[from..to].to_vec()).ok()
}

#[cfg(test)]
mod tests {
    use std::fs::read;

    use anyhow::Result;
    use pretty_assertions::assert_eq;

    use super::*;

    #[test]
    fn test_serverinfo() -> Result<()> {
        let data = read("tests/files/duel_holy_vs_dago[bravado]20240426-1659.mvd")?;

        let expected = Serverinfo {
            admin: Some("suom1 <suom1@irc.ax>".to_string()),
            deathmatch: Some(3),
            epoch: None,
            fpd: Some(142),
            fraglimit: None,
            gamedir: Some("qw".to_string()),
            hostname: Some("QUAKE.SE KTX:28501".to_string()),
            ktxmode: None,
            ktxver: Some("1.42".to_string()),
            map: Some("bravado".to_string()),
            matchtag: None,
            maxclients: Some(2),
            maxfps: Some(77),
            maxspectators: Some(12),
            mode: Some("1on1".to_string()),
            needpass: None,
            pm_ktjump: Some(1),
            progs: Some("so".to_string()),
            qvm: Some("so".to_string()),
            serverdemo: Some("duel_holy_vs_dago[bravado]20240426-1659.mvd".to_string()),
            status: Some("Countdown".to_string()),
            sv_antilag: Some(2),
            teamplay: None,
            timelimit: Some(10),
            version: Some("MVDSV 0.36".to_string()),
            z_ext: Some(511),
        };

        assert_eq!(serverinfo(&data), Some(expected));

        Ok(())
    }

    #[test]
    fn test_serverinfo_string() -> Result<()> {
        assert_eq!(
            serverinfo_string(&read("tests/files/duel_holy_vs_dago[bravado]20240426-1659.mvd")?),
            Some(
                r#"\maxfps\77\pm_ktjump\1\*version\MVDSV 0.36\*z_ext\511\*admin\suom1 <suom1@irc.ax>\ktxver\1.42\sv_antilag\2\maxspectators\12\*gamedir\qw\timelimit\10\deathmatch\3\mode\1on1\hostname\QUAKE.SE KTX:28501\fpd\142\*qvm\so\*progs\so\maxclients\2\map\bravado\status\Countdown\serverdemo\duel_holy_vs_dago[bravado]20240426-1659.mvd"#.to_string()
            )
        );

        assert_eq!(
            serverinfo_string(&read("tests/files/4on4_oeks_vs_tsq[dm2]20240426-1716.mvd")?),
            Some(
                r#"\maxfps\77\pm_ktjump\1\*version\MVDSV 0.36\*z_ext\511\*admin\suom1 <suom1@irc.ax>\ktxver\1.42\sv_antilag\2\maxspectators\12\teamplay\2\*gamedir\qw\maxclients\8\timelimit\20\deathmatch\1\mode\4on4\matchtag\tsq-axe lan\hostname\QUAKE.SE KTX:28502\fpd\142\*qvm\so\*progs\so\map\dm2\status\Countdown\serverdemo\4on4_oeks_vs_tsq[dm2]20240426-1716.mvd"#.to_string()
            )
        );

        assert_eq!(
            serverinfo_string(&read("tests/files/duel_equ_vs_kaboom[povdmm4]20240422-1038.mvd")?),
            Some(
                r#"\maxfps\77\pm_ktjump\1\*version\MVDSV 1.01-dev\*z_ext\511\maxspectators\12\*gamedir\qw\sv_antilag\2\*admin\ERRH @ https://discord.quake.world\ktxver\1.44-dev\mode\1on1\maxclients\2\timelimit\3\deathmatch\4\hostname\de.quake.world:27502 [QW-Group]\fpd\142\*qvm\so\*progs\so\map\povdmm4\status\Countdown\serverdemo\duel_equ_vs_kaboom[povdmm4]20240422-1038.mvd\epoch\1713782300"#.to_string()
            )
        );

        Ok(())
    }
}