livesplit_core/run/parser/
urn.rs1use crate::{platform::prelude::*, Run, Segment, Time, TimeSpan};
4use alloc::borrow::Cow;
5use core::result::Result as StdResult;
6use serde::Deserialize;
7use serde_json::Error as JsonError;
8
9#[derive(Debug, snafu::Snafu)]
12#[snafu(context(suffix(false)))]
13pub enum Error {
14 Json {
16 #[cfg_attr(not(feature = "std"), snafu(source(false)))]
18 source: JsonError,
19 },
20}
21
22pub type Result<T> = StdResult<T, Error>;
24
25#[derive(Deserialize)]
26struct Splits<'a> {
27 #[serde(borrow)]
28 title: Option<Cow<'a, str>>,
29 attempt_count: Option<u32>,
30 start_delay: Option<TimeSpan>,
31 splits: Option<Vec<Split<'a>>>,
32}
33
34#[derive(Deserialize)]
35struct Split<'a> {
36 #[serde(borrow)]
37 title: Option<Cow<'a, str>>,
38 time: Option<TimeSpan>,
39 best_time: Option<TimeSpan>,
40 best_segment: Option<TimeSpan>,
41}
42
43fn parse_time(real_time: TimeSpan) -> Time {
44 let real_time = if real_time != TimeSpan::zero() {
46 Some(real_time)
47 } else {
48 None
49 };
50
51 Time::new().with_real_time(real_time)
52}
53
54pub fn parse(source: &str) -> Result<Run> {
56 let splits: Splits<'_> =
57 serde_json::from_str(source).map_err(|source| Error::Json { source })?;
58
59 let mut run = Run::new();
60
61 if let Some(title) = splits.title {
62 run.set_category_name(title);
63 }
64 if let Some(attempt_count) = splits.attempt_count {
65 run.set_attempt_count(attempt_count);
66 }
67 if let Some(start_delay) = splits.start_delay {
68 run.set_offset(-start_delay);
69 }
70
71 let mut attempt_history_index = 1;
76
77 if let Some(splits) = splits.splits {
78 for split in splits {
79 let mut segment = Segment::new(split.title.unwrap_or_default());
80 if let Some(time) = split.time {
81 segment.set_personal_best_split_time(parse_time(time));
82 }
83 if let Some(best_segment) = split.best_segment {
84 segment.set_best_segment_time(parse_time(best_segment));
85 }
86
87 if let Some(best_time) = split.best_time {
88 let best_split_time = parse_time(best_time);
89 if best_split_time.real_time.is_some() {
90 run.add_attempt_with_index(
91 Time::default(),
92 attempt_history_index,
93 None,
94 None,
95 None,
96 );
97
98 for already_inserted_segment in run.segments_mut() {
100 already_inserted_segment
101 .segment_history_mut()
102 .insert(attempt_history_index, Time::default());
103 }
104
105 segment
106 .segment_history_mut()
107 .insert(attempt_history_index, best_split_time);
108
109 attempt_history_index += 1;
110 }
111 }
112
113 run.push_segment(segment);
114 }
115 }
116
117 Ok(run)
118}