Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run parser: deserialize the AutoSplitterSettings #797

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/livesplit-auto-splitting/src/settings/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

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

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

/// A filter for a file selection setting.
#[derive(Clone)]
#[derive(Clone, Debug, PartialEq)]
pub enum FileFilter {
/// A filter that matches on the name of the file.
Name {
Expand Down Expand Up @@ -82,7 +82,7 @@ pub enum FileFilter {
}

/// An option for a choice setting.
#[derive(Clone, Eq, Hash, PartialEq)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ChoiceOption {
/// The unique identifier of the option. This is not meant to be shown to
/// the user and is only used to keep track of the option. This key is used
Expand Down
36 changes: 30 additions & 6 deletions src/auto_splitting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,11 +558,11 @@ use crate::{
};
pub use livesplit_auto_splitting::{settings, wasi_path};
use livesplit_auto_splitting::{
AutoSplitter, Config, CreationError, InterruptHandle, LogLevel, Timer as AutoSplitTimer,
TimerState,
AutoSplitter, CompiledAutoSplitter, Config, CreationError, InterruptHandle, LogLevel,
Timer as AutoSplitTimer, TimerState,
};
use snafu::Snafu;
use std::{fmt, fs, io, path::PathBuf, thread, time::Duration};
use std::{fmt, fs, io, path::PathBuf, sync::RwLock, thread, time::Duration};
use tokio::{
runtime,
sync::watch,
Expand Down Expand Up @@ -598,6 +598,7 @@ pub struct Runtime<T> {
interrupt_receiver: watch::Receiver<Option<InterruptHandle>>,
auto_splitter: watch::Sender<Option<AutoSplitter<Timer<T>>>>,
runtime: livesplit_auto_splitting::Runtime,
compiled_auto_splitter: RwLock<Option<CompiledAutoSplitter>>,
}

impl<T> Drop for Runtime<T> {
Expand Down Expand Up @@ -652,18 +653,32 @@ impl<T: event::CommandSink + TimerQuery + Send + 'static> Runtime<T> {
auto_splitter: sender,
// TODO: unwrap?
runtime: livesplit_auto_splitting::Runtime::new(Config::default()).unwrap(),
compiled_auto_splitter: RwLock::new(None),
}
}

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

let auto_splitter = self
let compiled_auto_splitter = self
.runtime
.compile(&data)
.map_err(|e| Error::LoadFailed { source: e })?
.instantiate(Timer(timer), None, None)
.map_err(|e| Error::LoadFailed { source: e })?;
self.instantiate(&compiled_auto_splitter, timer)?;
*self.compiled_auto_splitter.write().unwrap() = Some(compiled_auto_splitter);
Ok(())
}

/// Instantiates the compiled auto splitter.
fn instantiate(
&self,
compiled_auto_splitter: &CompiledAutoSplitter,
timer: T,
) -> Result<(), Error> {
let settings_map = timer.get_timer().run().auto_splitter_settings_map_load();
let auto_splitter = compiled_auto_splitter
.instantiate(Timer(timer), settings_map, None)
.map_err(|e| Error::LoadFailed { source: e })?;

self.auto_splitter
Expand All @@ -680,6 +695,15 @@ impl<T: event::CommandSink + TimerQuery + Send + 'static> Runtime<T> {
.map_err(|_| Error::ThreadStopped)
}

/// Reloads the auto splitter without re-compiling.
pub fn reload(&self, timer: T) -> Result<(), Error> {
self.unload()?;
if let Some(compiled_auto_splitter) = self.compiled_auto_splitter.read().unwrap().as_ref() {
self.instantiate(compiled_auto_splitter, timer)?;
}
Ok(())
}

/// Accesses a copy of the currently stored settings. The auto splitter can
/// change these at any time. If you intend to make modifications to the
/// settings, you need to set them again via
Expand Down
2 changes: 2 additions & 0 deletions src/platform/no_std/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod time;
pub use self::time::*;

#[allow(unused)]
pub struct RwLock<T>(core::cell::RefCell<T>);

#[allow(unused)]
impl<T> RwLock<T> {
pub fn new(value: T) -> Self {
Self(core::cell::RefCell::new(value))
Expand Down
24 changes: 24 additions & 0 deletions src/run/auto_splitter_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::run::parser::livesplit::Version;
use core::fmt::Debug;
use livesplit_auto_splitting::settings;

#[derive(Debug, Default, Clone, PartialEq)]
pub struct AutoSplitterSettings {
pub version: Version,
pub script_path: String,
pub custom_settings: settings::Map,
}

impl AutoSplitterSettings {
pub fn set_version(&mut self, version: Version) {
self.version = version;
}

pub fn set_script_path(&mut self, script_path: String) {
self.script_path = script_path;
}

pub fn set_custom_settings(&mut self, custom_settings: settings::Map) {
self.custom_settings = custom_settings;
}
}
43 changes: 43 additions & 0 deletions src/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
//! ```

mod attempt;

#[cfg(feature = "auto-splitting")]
mod auto_splitter_settings;
mod comparisons;
pub mod editor;
mod linked_layout;
Expand All @@ -35,6 +38,8 @@ pub use run_metadata::{CustomVariable, RunMetadata};
pub use segment::Segment;
pub use segment_history::SegmentHistory;

#[cfg(feature = "auto-splitting")]
use crate::run::auto_splitter_settings::AutoSplitterSettings;
use crate::{
comparison::{default_generators, personal_best, ComparisonGenerator, RACE_COMPARISON_PREFIX},
platform::prelude::*,
Expand Down Expand Up @@ -75,6 +80,8 @@ pub struct Run {
custom_comparisons: Vec<String>,
comparison_generators: ComparisonGenerators,
auto_splitter_settings: String,
#[cfg(feature = "auto-splitting")]
parsed_auto_splitter_settings: Option<AutoSplitterSettings>,
linked_layout: Option<LinkedLayout>,
}

Expand Down Expand Up @@ -128,6 +135,8 @@ impl Run {
custom_comparisons: vec![personal_best::NAME.to_string()],
comparison_generators: ComparisonGenerators(default_generators()),
auto_splitter_settings: String::new(),
#[cfg(feature = "auto-splitting")]
parsed_auto_splitter_settings: None,
linked_layout: None,
}
}
Expand Down Expand Up @@ -326,6 +335,40 @@ impl Run {
&mut self.auto_splitter_settings
}

/// Loads a copy of the Auto Splitter Settings as a settings map.
#[inline]
#[cfg(feature = "auto-splitting")]
pub fn auto_splitter_settings_map_load(
&self,
) -> Option<livesplit_auto_splitting::settings::Map> {
if let Some(p) = &self.parsed_auto_splitter_settings {
return Some(p.custom_settings.clone());
}
None
}

/// Stores a settings map into the parsed auto splitter settings.
#[cfg(feature = "auto-splitting")]
pub fn auto_splitter_settings_map_store(
&mut self,
settings_map: livesplit_auto_splitting::settings::Map,
) {
let p = &mut self.parsed_auto_splitter_settings;
match p {
None => {
if settings_map.is_empty() {
return;
}
let mut a = AutoSplitterSettings::default();
a.set_custom_settings(settings_map);
*p = Some(a);
}
Some(a) => {
a.set_custom_settings(settings_map);
}
}
}

/// Accesses the [`LinkedLayout`] of this `Run`. If a
/// [`Layout`](crate::Layout) is linked, it is supposed to be loaded to
/// visualize the `Run`.
Expand Down
Loading
Loading