Upgrade backend & wasm to USDPL next

This commit is contained in:
NGnius (Graham) 2023-06-04 14:48:58 -04:00
parent b52441f1ad
commit c88402e580
23 changed files with 2304 additions and 1561 deletions

1
.gitignore vendored
View File

@ -44,6 +44,7 @@ yalc.lock
/backend-rs/target
backend
/bin/backend
/src/rust/target
# packaged teasers
*.zip

1267
backend-rs/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,24 @@
[package]
name = "fantastic-rs"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
[dependencies]
usdpl-back = { version = "0.10", features = ["blocking"]}
usdpl-back = { version = "0.11", features = ["blocking"], path = "../../usdpl-rs/usdpl-back"}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nrpc = "0.6"
prost = "0.11"
tokio = { version = "1", features = ["sync"] }
# logging
log = "0.4"
simplelog = "0.12"
[build-dependencies]
usdpl-build = { version = "0.11", path = "../../usdpl-rs/usdpl-build" }
[profile.release]
debug = false
strip = true

9
backend-rs/build.rs Normal file
View File

@ -0,0 +1,9 @@
fn main() {
//println!("CWD: {}", std::env::current_dir().unwrap().display());
usdpl_build::back::build([
format!("{}/protos/fantastic.proto", std::env::current_dir().unwrap().display())
].into_iter(),
[
format!("{}/protos/", std::env::current_dir().unwrap().display())
].into_iter())
}

View File

@ -1,11 +1,13 @@
#!/bin/bash
#cargo build --release --target x86_64-unknown-linux-musl
cargo build --target x86_64-unknown-linux-musl
#cargo build --target x86_64-unknown-linux-musl
#cross build --release
cargo build
mkdir -p ../bin
#cp ./target/x86_64-unknown-linux-musl/release/fantastic-rs ../bin/backend
cp ./target/x86_64-unknown-linux-musl/debug/fantastic-rs ../bin/backend
#cp ./target/release/fantastic-rs ../bin/backend
#cp --preserve=mode ./target/x86_64-unknown-linux-musl/release/fantastic-rs ../bin/backend
#cp --preserve=mode ./target/x86_64-unknown-linux-musl/debug/fantastic-rs ../bin/backend
#cp --preserve=mode ./target/release/fantastic-rs ../bin/backend
cp --preserve=mode ./target/debug/fantastic-rs ../bin/backend

View File

@ -0,0 +1,136 @@
syntax = "proto3";
package fantastic;
// The most amazing fan service
service Fan {
// Send back the exact same message as received
rpc echo (EchoMessage) returns (EchoMessage);
// Hello world
rpc hello (NameMessage) returns (HelloResponse);
// Fantastic version info
rpc version (Empty) returns (VersionMessage);
// Fantastic version number string
rpc version_str (Empty) returns (VersionDisplayMessage);
// Rust name (fantastic)
rpc name (Empty) returns (NameMessage);
// Get fan speed
rpc get_fan_rpm (Empty) returns (RpmMessage);
// Get system temperature
rpc get_temperature (Empty) returns (TemperatureMessage);
// Set custom fan control enabled
rpc set_enable (EnablementMessage) returns (EnablementMessage);
// Get custon fan control status
rpc get_enable (Empty) returns (EnablementMessage);
// Set fan control interpolation
rpc set_interpolate (EnablementMessage) returns (EnablementMessage);
// Get fan control interpolation
rpc get_interpolate (Empty) returns (EnablementMessage);
// Get fan control curve
rpc get_curve_x (Empty) returns (CurveMessageX);
// Get fan control curve
rpc get_curve_y (Empty) returns (CurveMessageY);
// Add a new point to the fan curve
rpc add_curve_point (GraphPoint) returns (Empty);
// Remove a point from the fan curve
rpc remove_curve_point (IndexMessage) returns (Empty);
/*
.register("echo", api::echo)
.register("hello", api::hello)
.register("version", api::version)
.register("name", api::name)
.register("get_fan_rpm", api::get_fan_rpm)
.register("get_temperature", api::get_temperature)
.register("set_enable", api::set_enable_gen(&runtime))
.register("get_enable", api::get_enable_gen(&runtime))
.register("set_interpolate", api::set_interpolate_gen(&runtime))
.register("get_interpolate", api::get_interpolate_gen(&runtime))
.register("get_curve", api::get_curve_gen(&runtime))
.register("add_curve_point", api::add_curve_point_gen(&runtime))
.register("remove_curve_point", api::remove_curve_point_gen(&runtime))
*/
}
// The request and response message for Echo
message EchoMessage {
string msg = 1;
}
message NameMessage {
string name = 1;
}
message HelloResponse {
string phrase = 1;
}
message Empty {
bool ok = 1;
}
message VersionMessage {
int32 major = 1;
int32 minor = 2;
int32 patch = 3;
//string display = 4;
}
message VersionDisplayMessage {
string display = 1;
}
message VersionStr {
string version_str = 1;
}
message RpmMessage {
uint64 rpm = 1;
}
message TemperatureMessage {
double temperature = 1;
}
message EnablementMessage {
bool is_enabled = 1;
}
message GraphPoint {
double x = 1;
double y = 2;
}
/*message CurveMessage {
//repeated GraphPoint points = 1;
repeated double x = 1;
repeated double y = 2;
}*/
message CurveMessageX {
//repeated GraphPoint points = 1;
repeated double x = 1;
}
message CurveMessageY {
//repeated GraphPoint points = 1;
repeated double y = 2;
}
message IndexMessage {
uint64 index = 1;
}

View File

@ -1,259 +1,183 @@
use usdpl_back::core::serdes::Primitive;
use crate::services::fantastic::*;
use super::control::ControlRuntime;
use super::json::GraphPointJson;
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub const NAME: &'static str = env!("CARGO_PKG_NAME");
pub fn hello(params: Vec<Primitive>) -> Vec<Primitive> {
if let Some(Primitive::String(name)) = params.get(0) {
vec![Primitive::String(format!("Hello {}", name))]
} else {
vec![]
}
pub struct FanService {
ctrl: ControlRuntime,
}
pub fn echo(params: Vec<Primitive>) -> Vec<Primitive> {
params
}
pub fn version(_: Vec<Primitive>) -> Vec<Primitive> {
vec![VERSION.into()]
}
pub fn name(_: Vec<Primitive>) -> Vec<Primitive> {
vec![NAME.into()]
}
pub fn get_fan_rpm(_: Vec<Primitive>) -> Vec<Primitive> {
if let Some(rpm) = crate::sys::read_fan() {
log::debug!("get_fan_rpm() success: {}", rpm);
vec![rpm.into()]
} else {
log::error!("get_fan_rpm failed to read fan speed");
Vec::new()
}
}
pub fn get_temperature(_: Vec<Primitive>) -> Vec<Primitive> {
if let Some(temperature) = crate::sys::read_thermal_zone(0) {
let real_temp = temperature as f64 / 1000.0;
log::debug!("get_temperature() success: {}", real_temp);
vec![real_temp.into()]
} else {
log::error!("get_fan_rpm failed to read fan speed");
Vec::new()
}
}
pub fn set_enable_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
let runtime_state = runtime.state_clone();
move |params| {
if let Some(Primitive::Bool(enabled)) = params.get(0) {
let mut settings = match runtime_settings.write() {
Ok(x) => x,
Err(e) => {
log::error!("set_enable failed to acquire settings write lock: {}", e);
return vec![];
}
};
if settings.enable != *enabled {
settings.enable = *enabled;
let mut state = match runtime_state.write() {
Ok(x) => x,
Err(e) => {
log::error!("set_enable failed to acquire state write lock: {}", e);
return vec![];
}
};
state.dirty = true;
log::debug!("set_enable({}) success", enabled);
}
vec![(*enabled).into()]
} else {
Vec::new()
impl FanService {
pub fn new(runtime: ControlRuntime) -> Self {
runtime.run();
Self {
ctrl: runtime,
}
}
}
pub fn get_enable_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
move |_| {
let lock = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("get_enable failed to acquire settings read lock: {}", e);
return vec![];
}
};
log::debug!("get_enable() success");
vec![lock.enable.into()]
}
}
pub fn set_interpolate_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
let runtime_state = runtime.state_clone();
move |params| {
if let Some(Primitive::Bool(enabled)) = params.get(0) {
let mut settings = match runtime_settings.write() {
Ok(x) => x,
Err(e) => {
log::error!("set_enable failed to acquire settings write lock: {}", e);
return vec![];
}
};
if settings.interpolate != *enabled {
settings.interpolate = *enabled;
let mut state = match runtime_state.write() {
Ok(x) => x,
Err(e) => {
log::error!("set_interpolate failed to acquire state write lock: {}", e);
return vec![];
}
};
state.dirty = true;
log::debug!("set_interpolate({}) success", enabled);
}
vec![(*enabled).into()]
} else {
Vec::new()
#[usdpl_back::nrpc::_helpers::async_trait::async_trait]
impl IFan for FanService {
async fn echo(
&mut self,
input: EchoMessage,
) -> Result<EchoMessage, Box<dyn std::error::Error>> {
Ok(input)
}
}
}
pub fn get_interpolate_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
move |_| {
let lock = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("get_interpolate failed to acquire settings read lock: {}", e);
return vec![];
}
};
log::debug!("get_interpolate() success");
vec![lock.interpolate.into()]
}
}
fn curve_to_json(curve: &Vec<super::datastructs::GraphPoint>) -> serde_json::Result<String> {
let mut curve_points = Vec::<GraphPointJson>::with_capacity(curve.len());
for point in curve.iter() {
curve_points.push(point.clone().into());
}
serde_json::to_string(&curve_points)
}
pub fn get_curve_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
move |_| {
let lock = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("get_curve failed to acquire settings read lock: {}", e);
return vec![];
}
};
let json_str = match curve_to_json(&lock.curve) {
Ok(x) => x,
Err(e) => {
log::error!("get_curve failed to serialize points: {}", e);
return vec![];
}
};
log::debug!("get_curve() success");
vec![Primitive::Json(json_str)]
}
}
pub fn add_curve_point_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
let runtime_state = runtime.state_clone();
move |params| {
if let Some(Primitive::Json(json_str)) = params.get(0) {
let mut settings = match runtime_settings.write() {
Ok(x) => x,
Err(e) => {
log::error!("add_curve_point failed to acquire settings write lock: {}", e);
return vec![];
}
};
let new_point: GraphPointJson = match serde_json::from_str(&json_str) {
Ok(x) => x,
Err(e) => {
log::error!("add_curve_point failed deserialize point json: {}", e);
return vec![];
}
};
let version = settings.version;
settings.curve.push(super::datastructs::GraphPoint::from_json(new_point, version));
settings.sort_curve();
let mut state = match runtime_state.write() {
Ok(x) => x,
Err(e) => {
log::error!("add_curve_point failed to acquire state write lock: {}", e);
return vec![];
}
};
state.dirty = true;
let json_str = match curve_to_json(&settings.curve) {
Ok(x) => x,
Err(e) => {
log::error!("add_curve_point failed to serialize points: {}", e);
return vec![];
}
};
log::debug!("add_curve_point({}) success", json_str);
vec![Primitive::Json(json_str)]
} else {
Vec::new()
async fn hello(
&mut self,
input: NameMessage,
) -> Result<HelloResponse, Box<dyn std::error::Error>> {
Ok(HelloResponse {
phrase: format!("Hello {}", input.name)
})
}
}
}
pub fn remove_curve_point_gen(runtime: &ControlRuntime) -> impl Fn(Vec<Primitive>) -> Vec<Primitive> {
let runtime_settings = runtime.settings_clone();
let runtime_state = runtime.state_clone();
move |params| {
if let Some(Primitive::F64(index)) = params.get(0) {
let mut settings = match runtime_settings.write() {
Ok(x) => x,
Err(e) => {
log::error!("remove_curve_point failed to acquire settings write lock: {}", e);
return vec![];
async fn version(
&mut self,
_input: Empty,
) -> Result<VersionMessage, Box<dyn std::error::Error>> {
Ok(
VersionMessage {
major: 0,
minor: 0,
patch: 0,
//display: VERSION.to_string(),
}
};
let rounded = index.round();
if rounded >= 0.0 && rounded < settings.curve.len() as _ {
let index = rounded as usize;
settings.curve.swap_remove(index);
settings.sort_curve();
let mut state = match runtime_state.write() {
Ok(x) => x,
Err(e) => {
log::error!("remove_curve_point failed to acquire state write lock: {}", e);
return vec![];
}
};
state.dirty = true;
let json_str = match curve_to_json(&settings.curve) {
Ok(x) => x,
Err(e) => {
log::error!("remove_curve_point failed to serialize points: {}", e);
return vec![];
}
};
log::debug!("remove_curve_point({}) success", json_str);
vec![Primitive::Json(json_str)]
)
}
async fn version_str(
&mut self,
_input: Empty,
) -> Result<VersionDisplayMessage, Box<dyn std::error::Error>> {
Ok(
VersionDisplayMessage {
display: VERSION.to_owned(),
}
)
}
async fn name(
&mut self,
_input: Empty,
) -> Result<NameMessage, Box<dyn std::error::Error>> {
Ok(
NameMessage {
name: NAME.to_string(),
}
)
}
async fn get_fan_rpm(
&mut self,
_input: Empty,
) -> Result<RpmMessage, Box<dyn std::error::Error>> {
if let Some(rpm) = crate::sys::read_fan() {
log::debug!("get_fan_rpm() success: {}", rpm);
Ok(RpmMessage { rpm })
} else {
log::error!("remove_curve_point received index out of bounds: {} indexing array of length {}", index, settings.curve.len());
return vec![];
Err("Failed to read fan speed".into())
}
}
async fn get_temperature(
&mut self,
_input: Empty,
) -> Result<TemperatureMessage, Box<dyn std::error::Error>>{
if let Some(temperature) = crate::sys::read_thermal_zone(0) {
let real_temp = temperature as f64 / 1000.0;
log::debug!("get_temperature() success: {}", real_temp);
Ok(TemperatureMessage { temperature: real_temp })
} else {
Err("get_temperature failed to read thermal zone 0".into())
}
}
async fn set_enable(
&mut self,
input: EnablementMessage,
) -> Result<EnablementMessage, Box<dyn std::error::Error>>{
let mut settings = self.ctrl.settings().write().await;
if settings.enable != input.is_enabled {
let mut state = self.ctrl.state().write().await;
settings.enable = input.is_enabled;
state.dirty = true;
}
log::debug!("set_enable({}) success", input.is_enabled);
Ok(input)
}
async fn get_enable(
&mut self,
_input: Empty,
) -> Result<EnablementMessage, Box<dyn std::error::Error>>{
let is_enabled = self.ctrl.settings().read().await.enable;
log::debug!("get_enable() success");
Ok(EnablementMessage { is_enabled })
}
async fn set_interpolate(
&mut self,
input: EnablementMessage,
) -> Result<EnablementMessage, Box<dyn std::error::Error>>{
let mut settings = self.ctrl.settings().write().await;
if settings.interpolate != input.is_enabled {
let mut state = self.ctrl.state().write().await;
settings.interpolate = input.is_enabled;
state.dirty = true;
}
log::debug!("set_interpolate({}) success", input.is_enabled);
Ok(input)
}
async fn get_interpolate(
&mut self,
_input: Empty,
) -> Result<EnablementMessage, Box<dyn std::error::Error>>{
let is_enabled = self.ctrl.settings().read().await.interpolate;
log::debug!("get_interpolate() success");
Ok(EnablementMessage { is_enabled })
}
async fn get_curve_x(
&mut self,
_input: Empty,
) -> Result<CurveMessageX, Box<dyn std::error::Error>>{
let settings = self.ctrl.settings().read().await;
let x = settings.curve.iter().map(|p| p.x).collect();
log::debug!("get_curve_x() success");
Ok(CurveMessageX { x })
}
async fn get_curve_y(
&mut self,
_input: Empty,
) -> Result<CurveMessageY, Box<dyn std::error::Error>>{
let settings = self.ctrl.settings().read().await;
let y = settings.curve.iter().map(|p| p.y).collect();
log::debug!("get_curve_x() success");
Ok(CurveMessageY { y })
}
async fn add_curve_point(
&mut self,
point: GraphPoint,
) -> Result<Empty, Box<dyn std::error::Error>>{
let mut settings = self.ctrl.settings().write().await;
settings.curve.push(super::datastructs::GraphPoint {
x: point.x,
y: point.y
});
settings.sort_curve();
let mut state = self.ctrl.state().write().await;
state.dirty = true;
Ok(Empty { ok: true })
}
async fn remove_curve_point(
&mut self,
input: IndexMessage,
) -> Result<Empty, Box<dyn std::error::Error>>{
let mut settings = self.ctrl.settings().write().await;
let i = input.index as usize;
if settings.curve.len() < i {
settings.curve.swap_remove(i);
settings.sort_curve();
let mut state = self.ctrl.state().write().await;
state.dirty = true;
Ok(Empty { ok: true })
} else {
Ok(Empty { ok: false })
}
} else {
Vec::new()
}
}
}

View File

@ -1,6 +1,7 @@
//! Fan control
use std::sync::{RwLock, Arc};
use std::sync::Arc;
use tokio::sync::RwLock;
use std::thread;
use std::time::{Duration, Instant};
@ -33,6 +34,14 @@ impl ControlRuntime {
self.state.clone()
}
pub(crate) fn settings(&self) -> &'_ RwLock<Settings> {
&self.settings
}
pub(crate) fn state(&self) -> &'_ RwLock<State> {
&self.state
}
pub fn run(&self) -> thread::JoinHandle<()> {
let runtime_settings = self.settings_clone();
let runtime_state = self.state_clone();
@ -44,20 +53,8 @@ impl ControlRuntime {
// resumed from sleep; do fan re-init
log::debug!("Detected resume from sleep, overriding fan again");
{
let state = match runtime_state.read() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire state read lock: {}", e);
continue;
}
};
let settings = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire settings read lock: {}", e);
continue;
}
};
let state = runtime_state.blocking_read();
let settings = runtime_settings.blocking_read();
if settings.enable {
Self::on_set_enable(&settings, &state);
}
@ -65,46 +62,22 @@ impl ControlRuntime {
}
start_time = Instant::now();
{ // save to file
let state = match runtime_state.read() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire state read lock: {}", e);
continue;
}
};
let state = runtime_state.blocking_read();
if state.dirty {
// save settings to file
let settings = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire settings read lock: {}", e);
continue;
}
};
let settings = runtime_settings.blocking_read();
let settings_json: SettingsJson = settings.clone().into();
if let Err(e) = settings_json.save(settings_path(&state.home)) {
log::error!("SettingsJson.save({}) error: {}", settings_path(&state.home).display(), e);
}
Self::on_set_enable(&settings, &state);
drop(state);
let mut state = match runtime_state.write() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire state write lock: {}", e);
continue;
}
};
let mut state = runtime_state.blocking_write();
state.dirty = false;
}
}
{ // fan control
let settings = match runtime_settings.read() {
Ok(x) => x,
Err(e) => {
log::error!("runtime failed to acquire settings read lock: {}", e);
continue;
}
};
let settings = runtime_settings.blocking_read();
if settings.enable {
Self::enforce_jupiter_status(true);
Self::do_fan_control(&settings);

View File

@ -6,7 +6,13 @@ mod sys;
use simplelog::{WriteLogger, LevelFilter};
use usdpl_back::Instance;
#[allow(missing_docs)]
#[allow(dead_code)]
pub mod services {
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}
use services::fantastic::FanServer;
const PORT: u16 = 44444;
@ -20,9 +26,14 @@ fn main() -> Result<(), ()> {
log::info!("Starting back-end ({} v{})", api::NAME, api::VERSION);
println!("Starting back-end ({} v{})", api::NAME, api::VERSION);
let runtime = control::ControlRuntime::new();
runtime.run();
Instance::new(PORT)
usdpl_back::Server::new(PORT)
.register(FanServer::new(
api::FanService::new(control::ControlRuntime::new())
))
.run_blocking()
.unwrap();
Ok(())
/*Instance::new(PORT)
.register("echo", api::echo)
.register("hello", api::hello)
.register("version", api::version)
@ -36,7 +47,7 @@ fn main() -> Result<(), ()> {
.register("get_curve", api::get_curve_gen(&runtime))
.register("add_curve_point", api::add_curve_point_gen(&runtime))
.register("remove_curve_point", api::remove_curve_point_gen(&runtime))
.run_blocking()
.run_blocking()*/
//Ok(())
//println!("Hello, world!");
}

View File

@ -42,7 +42,7 @@
"dependencies": {
"decky-frontend-lib": "~3.19.1",
"react-icons": "^4.7.1",
"usdpl-front": "file:src/usdpl"
"fantastic-wasm": "file:src/rust/pkg"
},
"pnpm": {
"peerDependencyRules": {

1069
src/rust/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

19
src/rust/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "fantastic-wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
usdpl-front = { version = "0.11", path = "../../../usdpl-rs/usdpl-front"}
nrpc = "0.6"
prost = "0.11"
[build-dependencies]
usdpl-build = { version = "0.11", path = "../../../usdpl-rs/usdpl-build" }
[features]
debug = ["usdpl-front/debug"]
decky = ["usdpl-front/decky"]

15
src/rust/build.rs Normal file
View File

@ -0,0 +1,15 @@
fn main() {
println!("CWD: {}", std::env::current_dir().unwrap().display());
usdpl_build::front::build(
[format!(
"{}/../../backend-rs/protos/fantastic.proto",
std::env::current_dir().unwrap().display()
)]
.into_iter(),
[format!(
"{}/../../backend-rs/protos/",
std::env::current_dir().unwrap().display()
)]
.into_iter(),
)
}

19
src/rust/build.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
if [ -n "$1" ]; then
if [ "$1" == "--help" ]; then
echo "Usage:
$0 [decky|crankshaft|<nothing>]"
exit 0
elif [ "$1" == "decky" ]; then
echo "Building WASM module for decky framework"
RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features decky,$2
else
echo "Unsupported plugin framework \`$1\`"
exit 1
fi
else
echo "WARNING: Building for any plugin framework, which may not work for every framework"
RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features debug,$2
fi
python3 ./scripts/generate_embedded_wasm.py

View File

@ -0,0 +1,45 @@
import base64
if __name__ == "__main__":
print("Embedding WASM into udspl_front.js")
# assumption: current working directory (relative to this script) is ../
# assumption: release wasm binary at ./pkg/usdpl_bg.wasm
with open("./pkg/fantastic_wasm_bg.wasm", mode="rb") as infile:
with open("./pkg/fantastic_wasm.js", mode="ab") as outfile:
outfile.write("\n\n// USDPL customization\nconst encoded = \"".encode())
encoded = base64.b64encode(infile.read())
outfile.write(encoded)
outfile.write("\";\n\n".encode())
outfile.write(
"""function asciiToBinary(str) {
if (typeof atob === 'function') {
return atob(str)
} else {
return new Buffer(str, 'base64').toString('binary');
}
}
function decode() {
var binaryString = asciiToBinary(encoded);
var bytes = new Uint8Array(binaryString.length);
for (var i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return (async function() {
return new Response(bytes.buffer, {
status: 200,
statusText: 'OK',
headers: {
'Content-Type': 'application/wasm'
}
});
})();
}
export function init_embedded() {
return init(decode())
}
""".encode())
with open("./pkg/usdpl_front.d.ts", "a") as outfile:
outfile.write("\n\n// USDPL customization\nexport function init_embedded();\n")
print("Done: Embedded WASM into udspl_front.js")

5
src/rust/src/lib.rs Normal file
View File

@ -0,0 +1,5 @@
#[allow(missing_docs)]
#[allow(dead_code)]
pub mod services {
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}

View File

@ -1,9 +0,0 @@
[![Crates.io](https://img.shields.io/crates/v/usdpl-front?style=flat-square)](https://crates.io/crates/usdpl-front)
# usdpl-front-front
Front-end library to be called from Javascript.
Targets WASM.
In true Javascript tradition, this part of the library does not support error handling.

View File

@ -1,21 +0,0 @@
{
"name": "usdpl-front",
"collaborators": [
"NGnius (Graham) <ngniusness@gmail.com>"
],
"description": "Universal Steam Deck Plugin Library front-end designed for WASM",
"version": "0.10.0",
"license": "GPL-3.0-only",
"repository": {
"type": "git",
"url": "https://github.com/NGnius/usdpl-rs"
},
"files": [
"usdpl_front_bg.wasm",
"usdpl_front.js",
"usdpl_front.d.ts"
],
"module": "usdpl_front.js",
"types": "usdpl_front.d.ts",
"sideEffects": false
}

View File

@ -1,13 +0,0 @@
#!/bin/bash
git clone https://github.com/NGnius/usdpl-rs usdpl-rs
cd usdpl-rs/usdpl-front/
./build.sh $1 $2
cd ../..
cp -f ./usdpl-rs/usdpl-front/pkg/* ./
#rm ./.gitignore
rm -rf ./usdpl-rs

View File

@ -1,105 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Initialize the front-end library
* @param {number} port
*/
export function init_usdpl(port: number): void;
/**
* Get the targeted plugin framework, or "any" if unknown
* @returns {string}
*/
export function target_usdpl(): string;
/**
* Get the UDSPL front-end version
* @returns {string}
*/
export function version_usdpl(): string;
/**
* Get the targeted plugin framework, or "any" if unknown
* @param {string} key
* @param {any} value
* @returns {any}
*/
export function set_value(key: string, value: any): any;
/**
* Get the targeted plugin framework, or "any" if unknown
* @param {string} key
* @returns {any}
*/
export function get_value(key: string): any;
/**
* Call a function on the back-end.
* Returns null (None) if this fails for any reason.
* @param {string} name
* @param {any[]} parameters
* @returns {Promise<any>}
*/
export function call_backend(name: string, parameters: any[]): Promise<any>;
/**
* Initialize translation strings for the front-end
* @param {string} locale
* @returns {Promise<void>}
*/
export function init_tr(locale: string): Promise<void>;
/**
* Translate a phrase, equivalent to tr_n(msg_id, 0)
* @param {string} msg_id
* @returns {string}
*/
export function tr(msg_id: string): string;
/**
* Translate a phrase, retrieving the plural form for `n` items
* @param {string} msg_id
* @param {number} n
* @returns {string}
*/
export function tr_n(msg_id: string, n: number): string;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly init_usdpl: (a: number) => void;
readonly target_usdpl: (a: number) => void;
readonly version_usdpl: (a: number) => void;
readonly set_value: (a: number, b: number, c: number) => number;
readonly get_value: (a: number, b: number) => number;
readonly call_backend: (a: number, b: number, c: number, d: number) => number;
readonly init_tr: (a: number, b: number) => number;
readonly tr: (a: number, b: number, c: number) => void;
readonly tr_n: (a: number, b: number, c: number, d: number) => void;
readonly __wbindgen_export_0: (a: number) => number;
readonly __wbindgen_export_1: (a: number, b: number, c: number) => number;
readonly __wbindgen_export_2: WebAssembly.Table;
readonly __wbindgen_export_3: (a: number, b: number, c: number) => void;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_export_4: (a: number, b: number) => void;
readonly __wbindgen_export_5: (a: number) => void;
readonly __wbindgen_export_6: (a: number, b: number, c: number, d: number) => void;
}
export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {SyncInitInput} module
*
* @returns {InitOutput}
*/
export function initSync(module: SyncInitInput): InitOutput;
/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {InitInput | Promise<InitInput>} module_or_path
*
* @returns {Promise<InitOutput>}
*/
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
// USDPL customization
export function init_embedded();

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,20 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function init_usdpl(a: number): void;
export function target_usdpl(a: number): void;
export function version_usdpl(a: number): void;
export function set_value(a: number, b: number, c: number): number;
export function get_value(a: number, b: number): number;
export function call_backend(a: number, b: number, c: number, d: number): number;
export function init_tr(a: number, b: number): number;
export function tr(a: number, b: number, c: number): void;
export function tr_n(a: number, b: number, c: number, d: number): void;
export function __wbindgen_export_0(a: number): number;
export function __wbindgen_export_1(a: number, b: number, c: number): number;
export const __wbindgen_export_2: WebAssembly.Table;
export function __wbindgen_export_3(a: number, b: number, c: number): void;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function __wbindgen_export_4(a: number, b: number): void;
export function __wbindgen_export_5(a: number): void;
export function __wbindgen_export_6(a: number, b: number, c: number, d: number): void;