1use crate::{
4 prelude::*,
5 replay::{replay, Replay},
6};
7
8#[cfg_attr(feature = "ser-de", derive(Serialize, Deserialize))]
10#[derive(Debug, Clone, PartialEq)]
11pub struct ScoreList {
12 pub version: u32,
13 pub beatmaps: Vec<BeatmapScores>,
14}
15impl ScoreList {
16 pub fn from_bytes(bytes: &[u8]) -> Result<ScoreList, Error> {
18 scores(bytes).map(|(_rem, scores)| scores)
19 }
20
21 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<ScoreList, Error> {
23 Self::from_bytes(&fs::read(path)?)
24 }
25
26 pub fn to_writer<W: Write>(&self, mut out: W) -> io::Result<()> {
28 self.wr(&mut out)
29 }
30
31 pub fn save<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
33 self.to_writer(BufWriter::new(File::create(path)?))
34 }
35}
36
37#[cfg_attr(feature = "ser-de", derive(Serialize, Deserialize))]
39#[derive(Debug, Clone, PartialEq)]
40pub struct BeatmapScores {
41 pub hash: Option<String>,
44 pub scores: Vec<Replay>,
46}
47
48fn scores(bytes: &[u8]) -> Result<(&[u8], ScoreList), Error> {
49 let (rem, version) = int(bytes)?;
50 let (mut rem, len) = int(rem)?;
51 let mut beatmaps = Vec::with_capacity(len as usize);
52
53 for _ in 0..len {
54 let (rem_, beatmap_scores) = beatmap_scores(rem)?;
55 beatmaps.push(beatmap_scores);
56 rem = rem_;
57 }
58
59 let list = ScoreList { version, beatmaps };
60
61 Ok((rem, list))
62}
63
64fn beatmap_scores(bytes: &[u8]) -> Result<(&[u8], BeatmapScores), Error> {
65 let (rem, hash) = opt_string(bytes)?;
66 let (mut rem, len) = int(rem)?;
67 let mut scores = Vec::with_capacity(len as usize);
68
69 for _ in 0..len {
70 let (rem_, replay) = replay(rem, false)?;
71 rem = rem_;
72 scores.push(replay);
73 }
74
75 let scores = BeatmapScores { hash, scores };
76
77 Ok((rem, scores))
78}
79
80writer!(ScoreList [this,out] {
81 this.version.wr(out)?;
82 PrefixedList(&this.beatmaps).wr(out)?;
83});
84writer!(BeatmapScores [this,out] {
85 this.hash.wr(out)?;
86 PrefixedList(&this.scores).wr_args(out,None)?;
87});