Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
run: curl https://drager.github.io/wasm-pack/installer/init.sh -sSf | bash

- name: Build library
run: wasm-pack build --scope libresplit --target web --release
run: wasm-pack build --scope libresplit --target web --release --features wasm
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

- name: Build WASM library
run: wasm-pack build --scope libresplit --target web --release
run: wasm-pack build --scope libresplit --target web --release --features wasm

- name: Set up Node.js
uses: actions/setup-node@v4
Expand All @@ -36,4 +36,4 @@ jobs:

- name: Publish to npm
run: npm install -g npm@latest
- run: wasm-pack publish --target web --access public
- run: wasm-pack publish ./pkg --access public
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ version = "1.0.0"
edition = "2024"

[lib]
crate-type = ["cdylib"]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
wasm-bindgen = "0.2.104"
wasm-bindgen = { version = "0.2.123", optional = true }

serde = { version = "1.0.215", features = ["derive"] }
serde_json = "1.0.133"
spex = "0.2.2"

[features]
default = []
wasm = ["wasm-bindgen"]
62 changes: 56 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,65 @@
use std::io::Cursor;
use std::{
ffi::{CStr, CString},
io::Cursor,
os::raw::c_char,
ptr::null_mut,
};

use spex::parsing::XmlReader;
use wasm_bindgen::prelude::*;

mod libresplit;
mod livesplit;

#[wasm_bindgen]
pub fn convert(file: String) -> String {
// Shared logic for both interfaces.
fn convert_inner(file: &str) -> Result<String, String> {
let cursor = Cursor::new(file);
let xml = XmlReader::parse_auto(cursor).unwrap();
let xml = XmlReader::parse_auto(cursor).map_err(|e| e.to_string())?;
let livesplit_data = livesplit::LiveSplitFile::new(xml);
libresplit::LibreSplitFile::from_livesplit(livesplit_data).get()
Ok(libresplit::LibreSplitFile::from_livesplit(livesplit_data).get())
}

// Build the library for WASM targets.
// Used on the LibreSplit website, for converting splits.
// Accepts a LiveSplit XML file as a string and returns LibreSplit JSON.

#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;

#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub fn convert(file: String) -> String {
convert_inner(&file).unwrap_or_else(|e| format!("{{\"error\":\"{}\"}}", e))
}

// C FFI entrypoints used by the split editor.

// 'converter_convert' takes a null-terminated UTF-8 string and returns an owned C string.
#[unsafe(no_mangle)]
pub extern "C" fn converter_convert(input: *const c_char) -> *mut c_char {
if input.is_null() {
return null_mut();
}

let input = unsafe {
match CStr::from_ptr(input).to_str() {
Ok(s) => s,
Err(_) => return null_mut(),
}
};

match convert_inner(input) {
Ok(output) => CString::new(output).unwrap().into_raw(),
Err(error) => CString::new(format!("{{\"error\":\"{}\"}}", error))
.unwrap()
.into_raw(),
}
}

// The caller must free the returned pointer with 'converter_free_string'.
#[unsafe(no_mangle)]
pub extern "C" fn converter_free_string(ptr: *mut c_char) {
if !ptr.is_null() {
unsafe {
let _ = CString::from_raw(ptr);
}
}
}
Loading