livesplit_core/run/parser/
shit_split.rs1use crate::{timing, GameTime, Run, Segment, TimeSpan};
4use core::{num::ParseIntError, result::Result as StdResult};
5use snafu::{OptionExt, ResultExt};
6
7#[derive(Debug, snafu::Snafu)]
10#[snafu(context(suffix(false)))]
11pub enum Error {
12 Empty,
14 ExpectedCategoryName,
16 ExpectedAttemptCount,
18 ParseAttemptCount {
20 source: ParseIntError,
22 },
23 ExpectedWorldName,
25 ExpectedWorldTime,
27 ParseWorldTime {
29 source: timing::ParseError,
31 },
32}
33
34pub type Result<T> = StdResult<T, Error>;
36
37pub fn parse(source: &str) -> Result<Run> {
39 let mut lines = source.lines();
40
41 let line = lines.next().context(Empty)?;
42
43 let mut splits = line.split('|');
44 let category_name = splits.next().context(ExpectedCategoryName)?;
45
46 let mut run = Run::new();
47
48 run.set_category_name(
49 category_name
50 .strip_prefix('#')
51 .ok_or(Error::ExpectedCategoryName)?,
52 );
53 run.set_attempt_count(
54 splits
55 .next()
56 .context(ExpectedAttemptCount)?
57 .parse()
58 .context(ParseAttemptCount)?,
59 );
60 let mut total_time = TimeSpan::zero();
61 let mut next_line = lines.next();
62 while let Some(line) = next_line {
63 if line.is_empty() {
64 break;
65 }
66 let mut splits = line.split('|');
67 let world_name = splits.next().context(ExpectedWorldName)?;
68 total_time += splits
69 .next()
70 .context(ExpectedWorldTime)?
71 .parse()
72 .context(ParseWorldTime)?;
73 next_line = lines.next();
74 let mut has_acts = false;
75 while let Some(line) = next_line {
76 if let Some(segment_name) = line.strip_prefix('*') {
77 run.push_segment(Segment::new(segment_name));
78 has_acts = true;
79 next_line = lines.next();
80 } else {
81 next_line = Some(line);
82 break;
83 }
84 }
85 let time = GameTime(Some(total_time)).into();
86 if has_acts {
87 run.segments_mut()
88 .last_mut()
89 .unwrap()
90 .set_personal_best_split_time(time);
91 } else {
92 let mut segment = Segment::new(world_name);
93 segment.set_personal_best_split_time(time);
94 run.push_segment(segment);
95 }
96 }
97
98 Ok(run)
99}