Skip to content

Commit

Permalink
Merge pull request LiveSplit#289 from TheEssenceOfDarkness/layout-sta…
Browse files Browse the repository at this point in the history
…te-capi

capi: Expose Layout State object
  • Loading branch information
CryZe committed Jan 29, 2020
2 parents 71283fb + a49a4c2 commit fe55323
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
7 changes: 7 additions & 0 deletions capi/src/layout.rs
Expand Up @@ -3,6 +3,7 @@

use super::{get_file, output_vec, release_file, str, Json};
use crate::component::OwnedComponent;
use crate::layout_state::OwnedLayoutState;
use livesplit_core::layout::{parser, LayoutSettings};
use livesplit_core::{Layout, Timer};
use std::io::{BufReader, Cursor};
Expand Down Expand Up @@ -86,6 +87,12 @@ pub unsafe extern "C" fn Layout_parse_original_livesplit(
}
}

/// Calculates and returns the layout's state based on the timer provided.
#[no_mangle]
pub extern "C" fn Layout_state(this: &mut Layout, timer: &Timer) -> OwnedLayoutState {
Box::new(this.state(timer))
}

/// Calculates the layout's state based on the timer provided and encodes it as
/// JSON. You can use this to visualize all of the components of a layout.
#[no_mangle]
Expand Down
157 changes: 157 additions & 0 deletions capi/src/layout_state.rs
@@ -0,0 +1,157 @@
//! The state object describes the information to visualize for an entire
//! layout. Use this with care, as invalid usage will result in a panic.
//!
//! Specifically, you should avoid doing the following:
//!
//! - Using out of bounds indices.
//! - Using the wrong getter function on the wrong type of component.

use livesplit_core::component::{
blank_space::State as BlankSpaceComponentState,
detailed_timer::State as DetailedTimerComponentState, graph::State as GraphComponentState,
key_value::State as KeyValueComponentState, separator::State as SeparatorComponentState,
splits::State as SplitsComponentState, text::State as TextComponentState,
timer::State as TimerComponentState, title::State as TitleComponentState,
};
use livesplit_core::layout::{ComponentState, LayoutState};
use std::os::raw::c_char;

/// type
pub type OwnedLayoutState = Box<LayoutState>;

/// drop
#[no_mangle]
pub extern "C" fn LayoutState_drop(this: OwnedLayoutState) {
drop(this);
}

/// Gets the number of Components in the Layout State.
#[no_mangle]
pub extern "C" fn LayoutState_len(this: &LayoutState) -> usize {
this.components.len()
}

/// Returns a string describing the type of the Component at the specified
/// index.
#[no_mangle]
pub extern "C" fn LayoutState_component_type(this: &LayoutState, index: usize) -> *const c_char {
(match this.components[index] {
ComponentState::BlankSpace(_) => "BlankSpace\0",
ComponentState::DetailedTimer(_) => "DetailedTimer\0",
ComponentState::Graph(_) => "Graph\0",
ComponentState::KeyValue(_) => "KeyValue\0",
ComponentState::Separator(_) => "Separator\0",
ComponentState::Splits(_) => "Splits\0",
ComponentState::Text(_) => "Text\0",
ComponentState::Timer(_) => "Timer\0",
ComponentState::Title(_) => "Title\0",
}).as_ptr().cast()
}

/// Gets the Blank Space component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_blank_space(
this: &LayoutState,
index: usize,
) -> &BlankSpaceComponentState {
match &this.components[index] {
ComponentState::BlankSpace(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Detailed Timer component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_detailed_timer(
this: &LayoutState,
index: usize,
) -> &DetailedTimerComponentState {
match &this.components[index] {
ComponentState::DetailedTimer(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Graph component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_graph(
this: &LayoutState,
index: usize,
) -> &GraphComponentState {
match &this.components[index] {
ComponentState::Graph(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Key Value component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_key_value(
this: &LayoutState,
index: usize,
) -> &KeyValueComponentState {
match &this.components[index] {
ComponentState::KeyValue(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Separator component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_separator(
this: &LayoutState,
index: usize,
) -> &SeparatorComponentState {
match &this.components[index] {
ComponentState::Separator(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Splits component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_splits(
this: &LayoutState,
index: usize,
) -> &SplitsComponentState {
match &this.components[index] {
ComponentState::Splits(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Text component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_text(
this: &LayoutState,
index: usize,
) -> &TextComponentState {
match &this.components[index] {
ComponentState::Text(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Timer component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_timer(
this: &LayoutState,
index: usize,
) -> &TimerComponentState {
match &this.components[index] {
ComponentState::Timer(x) => x,
_ => panic!("wrong component state type"),
}
}

/// Gets the Title component state at the specified index.
#[no_mangle]
pub extern "C" fn LayoutState_component_as_title(
this: &LayoutState,
index: usize,
) -> &TitleComponentState {
match &this.components[index] {
ComponentState::Title(x) => x,
_ => panic!("wrong component state type"),
}
}
2 changes: 2 additions & 0 deletions capi/src/lib.rs
Expand Up @@ -29,6 +29,7 @@ pub mod hotkey_system;
pub mod key_value_component_state;
pub mod layout;
pub mod layout_editor;
pub mod layout_state;
pub mod parse_run_result;
pub mod pb_chance_component;
pub mod possible_time_save_component;
Expand All @@ -47,6 +48,7 @@ pub mod segment_history_element;
pub mod segment_history_iter;
pub mod segment_time_component;
pub mod separator_component;
pub mod separator_component_state;
pub mod setting_value;
pub mod shared_timer;
pub mod splits_component;
Expand Down
11 changes: 11 additions & 0 deletions capi/src/separator_component.rs
Expand Up @@ -2,7 +2,9 @@
//! separators between components.

use crate::component::OwnedComponent;
use crate::separator_component_state::OwnedSeparatorComponentState;
use livesplit_core::component::separator::Component as SeparatorComponent;
use livesplit_core::Timer;

/// type
pub type OwnedSeparatorComponent = Box<SeparatorComponent>;
Expand All @@ -25,3 +27,12 @@ pub extern "C" fn SeparatorComponent_drop(this: OwnedSeparatorComponent) {
pub extern "C" fn SeparatorComponent_into_generic(this: OwnedSeparatorComponent) -> OwnedComponent {
Box::new((*this).into())
}

/// Calculates the component's state based on the timer provided.
#[no_mangle]
pub extern "C" fn SeparatorComponent_state(
this: &mut SeparatorComponent,
timer: &Timer,
) -> OwnedSeparatorComponentState {
Box::new(this.state(timer))
}
12 changes: 12 additions & 0 deletions capi/src/separator_component_state.rs
@@ -0,0 +1,12 @@
//! The state object describes the information to visualize for this component.

use livesplit_core::component::separator::State as SeparatorComponentState;

/// type
pub type OwnedSeparatorComponentState = Box<SeparatorComponentState>;

/// drop
#[no_mangle]
pub extern "C" fn SeparatorComponentState_drop(this: OwnedSeparatorComponentState) {
drop(this);
}

0 comments on commit fe55323

Please sign in to comment.