osr_parser/
replay.rs

1use std::fs;
2
3#[cfg(feature = "lzma")]
4use std::io::Read;
5
6use super::error::ReplayError;
7use super::mode::Gamemode;
8use super::read::{read_byte, read_int, read_string};
9
10#[derive(Debug)]
11pub struct Replay {
12    pub gamemode: Gamemode,
13    pub version: u32,
14    pub beatmap_md5: Option<String>,
15    pub username: Option<String>,
16    pub replay_md5: Option<String>,
17    pub n300: u16,
18    pub n100: u16,
19    pub n50: u16,
20    pub geki: u16,
21    pub katu: u16,
22    pub misses: u16,
23    pub score: u32,
24    pub combo: u16,
25    pub perfect: u8,
26    pub mods: u32,
27    pub life_bar: Option<String>,
28    pub time_stamp: usize,
29    pub replay_length: u32,
30    pub replay_data: Vec<u8>,
31    pub score_id: usize,
32    pub mod_info: Option<f64>,
33}
34
35impl Replay {
36    pub fn read(path: &str) -> Result<Self, ReplayError> {
37        let mut content = fs::read(path)?;
38        let mut p = 0;
39
40        let mut _replay_length = 0;
41
42        Ok(Self {
43            gamemode     : Gamemode::from(read_byte(&mut p, &content)),
44            version      : read_int!(u32, &mut p, &content),
45            beatmap_md5  : read_string(&mut p, &mut content).ok(),
46            username     : read_string(&mut p, &mut content).ok(),
47            replay_md5   : read_string(&mut p, &mut content).ok(),
48            n300         : read_int!(u16, &mut p, &content),
49            n100         : read_int!(u16, &mut p, &content),
50            n50          : read_int!(u16, &mut p, &content),
51            geki         : read_int!(u16, &mut p, &content),
52            katu         : read_int!(u16, &mut p, &content),
53            misses       : read_int!(u16, &mut p, &content),
54            score        : read_int!(u32, &mut p, &content),
55            combo        : read_int!(u16, &mut p, &content),
56            perfect      : read_byte(&mut p, &content),
57            mods         : read_int!(u32, &mut p, &content),
58            life_bar     : read_string(&mut p, &mut content).ok(),
59            time_stamp   : read_int!(usize, &mut p, &content),
60            replay_length: {
61                _replay_length = read_int!(u32, &mut p, &content);
62                _replay_length
63            },
64            replay_data: {
65                let start = *&mut p;
66                *&mut p = _replay_length as usize;
67
68                content[start..(_replay_length as usize)].to_vec()
69            },
70            score_id: read_int!(usize, &mut p, &content),
71            mod_info: {
72                if *&mut p != content.len() {
73                    Some(read_int!(usize, &mut p, &content) as f64)
74                } else {
75                    None
76                }
77            }
78        })
79    }
80
81    #[cfg(feature = "lzma")]
82    pub fn parse_lzma(&mut self) -> Result<String, ReplayError> {
83        let mut reader = lzma::Reader::from(&*self.replay_data)?;
84        let mut stream = String::with_capacity(4096);
85
86        reader.read_to_string(&mut stream)?;
87        Ok(stream)
88    }
89}