Skip to content

Commit f691684

Browse files
RefraggAlexKnauth
authored andcommitted
Run parser: deserialize the AutoSplitterSettings
This commit implements the deserialization of the AutoSplitterSettings XML section of a LiveSplit splits file. This can surely use some improvements regarding the compatibility without the auto-splitting feature and some other things. I think it is good as a first step though and we can keep iterating on it.
1 parent 7649ba0 commit f691684

File tree

9 files changed

+662
-22
lines changed

9 files changed

+662
-22
lines changed

crates/livesplit-auto-splitting/src/settings/gui.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::Arc;
22

33
/// A setting widget that is meant to be shown to and modified by the user.
44
#[non_exhaustive]
5-
#[derive(Clone)]
5+
#[derive(Clone, PartialEq)]
66
pub struct Widget {
77
/// A unique identifier for this setting. This is not meant to be shown to
88
/// the user and is only used to keep track of the setting. This key is used
@@ -19,7 +19,7 @@ pub struct Widget {
1919
}
2020

2121
/// The type of a [`Widget`] and additional information about it.
22-
#[derive(Clone)]
22+
#[derive(Debug, Clone, PartialEq)]
2323
pub enum WidgetKind {
2424
/// A title that is shown to the user. It doesn't by itself store a value
2525
/// and is instead used to group settings together.
@@ -51,7 +51,7 @@ pub enum WidgetKind {
5151
}
5252

5353
/// A filter for a file selection setting.
54-
#[derive(Clone)]
54+
#[derive(Clone, Debug, PartialEq)]
5555
pub enum FileFilter {
5656
/// A filter that matches on the name of the file.
5757
Name {
@@ -82,7 +82,7 @@ pub enum FileFilter {
8282
}
8383

8484
/// An option for a choice setting.
85-
#[derive(Clone, Eq, Hash, PartialEq)]
85+
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
8686
pub struct ChoiceOption {
8787
/// The unique identifier of the option. This is not meant to be shown to
8888
/// the user and is only used to keep track of the option. This key is used

src/auto_splitting/mod.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,16 @@ use crate::{
570570
};
571571
use arc_swap::ArcSwapOption;
572572
use livesplit_auto_splitting::{
573-
AutoSplitter, Config, CreationError, LogLevel, Timer as AutoSplitTimer, TimerState,
573+
AutoSplitter, CompiledAutoSplitter, Config, CreationError, LogLevel,
574+
Timer as AutoSplitTimer, TimerState,
574575
};
575576
pub use livesplit_auto_splitting::{settings, wasi_path};
576577
use snafu::Snafu;
577578
use std::{
578579
fmt, fs, io,
579580
path::PathBuf,
580581
sync::{
581-
Condvar, Mutex,
582+
Condvar, Mutex, RwLock,
582583
mpsc::{self, Receiver, RecvTimeoutError, Sender},
583584
},
584585
thread,
@@ -614,6 +615,7 @@ pub struct Runtime<T: event::CommandSink + TimerQuery + Send + 'static> {
614615
shared_state: Arc<SharedState<T>>,
615616
changed_sender: Sender<()>,
616617
runtime: livesplit_auto_splitting::Runtime,
618+
compiled_auto_splitter: RwLock<Option<CompiledAutoSplitter>>,
617619
}
618620

619621
struct SharedState<T: 'static> {
@@ -688,18 +690,32 @@ impl<T: event::CommandSink + TimerQuery + Send + 'static> Runtime<T> {
688690
changed_sender,
689691
// TODO: unwrap?
690692
runtime: livesplit_auto_splitting::Runtime::new(Config::default()).unwrap(),
693+
compiled_auto_splitter: RwLock::new(None),
691694
}
692695
}
693696

694697
/// Attempts to load a wasm file containing an auto splitter module.
695698
pub fn load(&self, path: PathBuf, timer: T) -> Result<(), Error> {
696699
let data = fs::read(path).map_err(|e| Error::ReadFileFailed { source: e })?;
697700

698-
let auto_splitter = self
701+
let compiled_auto_splitter = self
699702
.runtime
700703
.compile(&data)
701-
.map_err(|e| Error::LoadFailed { source: e })?
702-
.instantiate(Timer(timer), None, None)
704+
.map_err(|e| Error::LoadFailed { source: e })?;
705+
self.instantiate(&compiled_auto_splitter, timer)?;
706+
*self.compiled_auto_splitter.write().unwrap() = Some(compiled_auto_splitter);
707+
Ok(())
708+
}
709+
710+
/// Instantiates the compiled auto splitter.
711+
fn instantiate(
712+
&self,
713+
compiled_auto_splitter: &CompiledAutoSplitter,
714+
timer: T,
715+
) -> Result<(), Error> {
716+
let settings_map = timer.get_timer().run().auto_splitter_settings_map_load();
717+
let auto_splitter = compiled_auto_splitter
718+
.instantiate(Timer(timer), settings_map, None)
703719
.map_err(|e| Error::LoadFailed { source: e })?;
704720

705721
self.shared_state
@@ -722,6 +738,15 @@ impl<T: event::CommandSink + TimerQuery + Send + 'static> Runtime<T> {
722738
.map_err(|_| Error::ThreadStopped)
723739
}
724740

741+
/// Reloads the auto splitter without re-compiling.
742+
pub fn reload(&self, timer: T) -> Result<(), Error> {
743+
self.unload()?;
744+
if let Some(compiled_auto_splitter) = self.compiled_auto_splitter.read().unwrap().as_ref() {
745+
self.instantiate(compiled_auto_splitter, timer)?;
746+
}
747+
Ok(())
748+
}
749+
725750
/// Accesses a copy of the currently stored settings. The auto splitter can
726751
/// change these at any time. If you intend to make modifications to the
727752
/// settings, you need to set them again via

src/run/auto_splitter_settings.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use crate::run::parser::livesplit::Version;
2+
use core::fmt::Debug;
3+
use livesplit_auto_splitting::settings;
4+
5+
#[derive(Debug, Default, Clone, PartialEq)]
6+
pub struct AutoSplitterSettings {
7+
pub version: Version,
8+
pub script_path: String,
9+
pub custom_settings: settings::Map,
10+
}
11+
12+
impl AutoSplitterSettings {
13+
pub fn set_version(&mut self, version: Version) {
14+
self.version = version;
15+
}
16+
17+
pub fn set_script_path(&mut self, script_path: String) {
18+
self.script_path = script_path;
19+
}
20+
21+
pub fn set_custom_settings(&mut self, custom_settings: settings::Map) {
22+
self.custom_settings = custom_settings;
23+
}
24+
}

src/run/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
//! ```
1616
1717
mod attempt;
18+
19+
#[cfg(feature = "auto-splitting")]
20+
mod auto_splitter_settings;
1821
mod comparisons;
1922
pub mod editor;
2023
mod linked_layout;
@@ -35,6 +38,8 @@ pub use run_metadata::{CustomVariable, RunMetadata};
3538
pub use segment::Segment;
3639
pub use segment_history::SegmentHistory;
3740

41+
#[cfg(feature = "auto-splitting")]
42+
use crate::run::auto_splitter_settings::AutoSplitterSettings;
3843
use crate::{
3944
AtomicDateTime, Time, TimeSpan, TimingMethod,
4045
comparison::{ComparisonGenerator, RACE_COMPARISON_PREFIX, default_generators, personal_best},
@@ -75,6 +80,8 @@ pub struct Run {
7580
custom_comparisons: Vec<String>,
7681
comparison_generators: ComparisonGenerators,
7782
auto_splitter_settings: String,
83+
#[cfg(feature = "auto-splitting")]
84+
parsed_auto_splitter_settings: Option<AutoSplitterSettings>,
7885
linked_layout: Option<LinkedLayout>,
7986
}
8087

@@ -128,6 +135,8 @@ impl Run {
128135
custom_comparisons: vec![personal_best::NAME.to_string()],
129136
comparison_generators: ComparisonGenerators(default_generators()),
130137
auto_splitter_settings: String::new(),
138+
#[cfg(feature = "auto-splitting")]
139+
parsed_auto_splitter_settings: None,
131140
linked_layout: None,
132141
}
133142
}
@@ -326,6 +335,40 @@ impl Run {
326335
&mut self.auto_splitter_settings
327336
}
328337

338+
/// Loads a copy of the Auto Splitter Settings as a settings map.
339+
#[inline]
340+
#[cfg(feature = "auto-splitting")]
341+
pub fn auto_splitter_settings_map_load(
342+
&self,
343+
) -> Option<livesplit_auto_splitting::settings::Map> {
344+
if let Some(p) = &self.parsed_auto_splitter_settings {
345+
return Some(p.custom_settings.clone());
346+
}
347+
None
348+
}
349+
350+
/// Stores a settings map into the parsed auto splitter settings.
351+
#[cfg(feature = "auto-splitting")]
352+
pub fn auto_splitter_settings_map_store(
353+
&mut self,
354+
settings_map: livesplit_auto_splitting::settings::Map,
355+
) {
356+
let p = &mut self.parsed_auto_splitter_settings;
357+
match p {
358+
None => {
359+
if settings_map.is_empty() {
360+
return;
361+
}
362+
let mut a = AutoSplitterSettings::default();
363+
a.set_custom_settings(settings_map);
364+
*p = Some(a);
365+
}
366+
Some(a) => {
367+
a.set_custom_settings(settings_map);
368+
}
369+
}
370+
}
371+
329372
/// Accesses the [`LinkedLayout`] of this `Run`. If a
330373
/// [`Layout`](crate::Layout) is linked, it is supposed to be loaded to
331374
/// visualize the `Run`.

0 commit comments

Comments
 (0)