Add translation functionality
This commit is contained in:
parent
9755eb24b7
commit
4745f0ae7e
11 changed files with 428 additions and 108 deletions
227
Cargo.lock
generated
227
Cargo.lock
generated
|
@ -17,7 +17,7 @@ version = "0.7.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
|
@ -87,6 +87,12 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
|
@ -133,12 +139,6 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -160,7 +160,7 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
@ -192,6 +192,18 @@ dependencies = [
|
|||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "current_locale"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0be8ddcccda8be68d8e31a421ceea7c79857404daa052434ae30ce2f402cd10"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
|
@ -211,6 +223,70 @@ dependencies = [
|
|||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||
dependencies = [
|
||||
"encoding-index-japanese",
|
||||
"encoding-index-korean",
|
||||
"encoding-index-simpchinese",
|
||||
"encoding-index-singlebyte",
|
||||
"encoding-index-tradchinese",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-japanese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-korean"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-simpchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-singlebyte"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-tradchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_index_tests"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
|
@ -293,11 +369,21 @@ version = "0.2.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gettext-ng"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2c86be871deb255ef65fc8395048a2505912c595f1eddc4da03aeb6fda5cf34"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.14"
|
||||
|
@ -453,7 +539,7 @@ version = "0.1.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -483,7 +569,16 @@ version = "0.4.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -492,12 +587,6 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
|
@ -569,6 +658,35 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2b2cbbfd8defa51ff24450a61d73b3ff3e158484ddd274a883e886e6fbaa78"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.14.0"
|
||||
|
@ -625,7 +743,7 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
|
@ -763,7 +881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
|
@ -775,7 +893,7 @@ version = "0.10.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.10.3",
|
||||
]
|
||||
|
@ -833,7 +951,7 @@ version = "3.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
|
@ -996,7 +1114,7 @@ version = "0.1.36"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
|
@ -1107,21 +1225,6 @@ name = "usdpl-back"
|
|||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58928ed65332c30b9b9be5140fcdab97e45db679a5845d829aa26492765272e5"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"hex",
|
||||
"log",
|
||||
"obfstr",
|
||||
"tokio",
|
||||
"usdpl-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"warp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usdpl-back"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
|
@ -1135,12 +1238,20 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "usdpl-core"
|
||||
version = "0.6.0"
|
||||
name = "usdpl-back"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"aes-gcm-siv",
|
||||
"base64",
|
||||
"hex-literal",
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"current_locale",
|
||||
"gettext-ng",
|
||||
"hex",
|
||||
"log",
|
||||
"obfstr",
|
||||
"tokio",
|
||||
"usdpl-core 0.9.0",
|
||||
"warp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1153,25 +1264,33 @@ dependencies = [
|
|||
"base64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usdpl-core"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"aes-gcm-siv",
|
||||
"base64",
|
||||
"hex-literal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usdpl-front"
|
||||
version = "0.7.0"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"hex",
|
||||
"js-sys",
|
||||
"obfstr",
|
||||
"usdpl-core 0.6.0",
|
||||
"usdpl-core 0.9.0",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
"wee_alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usdpl-rs"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
|
@ -1237,7 +1356,7 @@ version = "0.2.83"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
|
@ -1262,7 +1381,7 @@ version = "0.4.33"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
@ -1331,18 +1450,6 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"memory_units",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "usdpl-rs"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "usdpl-back"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only"
|
||||
repository = "https://github.com/NGnius/usdpl-rs"
|
||||
|
@ -8,14 +8,15 @@ readme = "README.md"
|
|||
description = "Universal Steam Deck Plugin Library back-end"
|
||||
|
||||
[features]
|
||||
default = ["blocking"]
|
||||
default = ["blocking", "translate"]
|
||||
decky = ["usdpl-core/decky"]
|
||||
crankshaft = ["usdpl-core/crankshaft"]
|
||||
blocking = ["tokio", "tokio/rt", "tokio/rt-multi-thread"] # synchronous API for async functionality, using tokio
|
||||
encrypt = ["usdpl-core/encrypt", "obfstr", "hex"]
|
||||
translate = ["usdpl-core/translate", "gettext-ng"]
|
||||
|
||||
[dependencies]
|
||||
usdpl-core = { version = "0.6.0", path = "../usdpl-core"}
|
||||
usdpl-core = { version = "0.9.0", path = "../usdpl-core"}
|
||||
|
||||
log = "0.4"
|
||||
|
||||
|
@ -31,3 +32,6 @@ async-recursion = "1.0.0"
|
|||
# encryption helpers
|
||||
obfstr = { version = "0.3", optional = true }
|
||||
hex = { version = "0.4", optional = true }
|
||||
|
||||
# translations
|
||||
gettext-ng = { version = "0.4.1", optional = true }
|
||||
|
|
|
@ -118,14 +118,16 @@ impl Instance {
|
|||
} else {
|
||||
socket::Packet::Invalid
|
||||
}
|
||||
}
|
||||
},
|
||||
socket::Packet::Many(packets) => {
|
||||
let mut result = Vec::with_capacity(packets.len());
|
||||
for packet in packets {
|
||||
result.push(Self::handle_call(packet, handlers).await);
|
||||
}
|
||||
socket::Packet::Many(result)
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "translate")]
|
||||
socket::Packet::Language(lang) => socket::Packet::Translations(get_all_translations(lang)),
|
||||
_ => socket::Packet::Invalid,
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +223,32 @@ impl Instance {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "translate")]
|
||||
fn get_all_translations(language: String) -> Vec<(String, Vec<String>)> {
|
||||
log::debug!("Loading translations for language `{}`...", language);
|
||||
let result = load_locale(&language);
|
||||
match result {
|
||||
Ok(catalog) => {
|
||||
let map = catalog.nalltext();
|
||||
let mut result = Vec::with_capacity(map.len());
|
||||
for (key, val) in map.iter() {
|
||||
result.push((key.to_owned().into(), val.iter().map(|x| x.into()).collect()));
|
||||
}
|
||||
result
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to load translations for language `{}`: {}", language, e);
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "translate")]
|
||||
fn load_locale(lang: &str) -> Result<gettext_ng::Catalog, gettext_ng::Error> {
|
||||
let file = std::fs::File::open(lang).map_err(|e| gettext_ng::Error::Io(e))?;
|
||||
gettext_ng::Catalog::parse(file)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[allow(unused_imports)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "usdpl-core"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only"
|
||||
repository = "https://github.com/NGnius/usdpl-rs"
|
||||
|
@ -12,6 +12,7 @@ default = []
|
|||
decky = []
|
||||
crankshaft = []
|
||||
encrypt = ["aes-gcm-siv"]
|
||||
translate = []
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
|
|
|
@ -24,6 +24,48 @@ impl<T: Dumpable> Dumpable for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T0: Dumpable, T1: Dumpable> Dumpable for (T0, T1) {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
Ok(
|
||||
self.0.dump(buffer)?
|
||||
+ self.1.dump(buffer)?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Dumpable, T1: Dumpable, T2: Dumpable> Dumpable for (T0, T1, T2) {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
Ok(
|
||||
self.0.dump(buffer)?
|
||||
+ self.1.dump(buffer)?
|
||||
+ self.2.dump(buffer)?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Dumpable, T1: Dumpable, T2: Dumpable, T3: Dumpable> Dumpable for (T0, T1, T2, T3) {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
Ok(
|
||||
self.0.dump(buffer)?
|
||||
+ self.1.dump(buffer)?
|
||||
+ self.2.dump(buffer)?
|
||||
+ self.3.dump(buffer)?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Dumpable, T1: Dumpable, T2: Dumpable, T3: Dumpable, T4: Dumpable> Dumpable for (T0, T1, T2, T3, T4) {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
Ok(
|
||||
self.0.dump(buffer)?
|
||||
+ self.1.dump(buffer)?
|
||||
+ self.2.dump(buffer)?
|
||||
+ self.3.dump(buffer)?
|
||||
+ self.4.dump(buffer)?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dumpable for bool {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
buffer.write(&[*self as u8]).map_err(DumpError::Io)
|
||||
|
@ -97,6 +139,11 @@ mod tests {
|
|||
&[3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 5, 0, 0, 0, 116, 101, 115, 116, 50]
|
||||
}
|
||||
|
||||
test_impl! {tuple2_dump_test, (0u8, 1u8), 2, &[0, 1]}
|
||||
test_impl! {tuple3_dump_test, (0u8, 1u8, 2u8), 3, &[0, 1, 2]}
|
||||
test_impl! {tuple4_dump_test, (0u8, 1u8, 2u8, 3u8), 4, &[0, 1, 2, 3]}
|
||||
test_impl! {tuple5_dump_test, (0u8, 1u8, 2u8, 3u8, 4u8), 5, &[0, 1, 2, 3, 4]}
|
||||
|
||||
test_impl! {bool_true_dump_test, true, 1, &[1]}
|
||||
test_impl! {bool_false_dump_test, false, 1, &[0]}
|
||||
|
||||
|
|
|
@ -38,6 +38,56 @@ impl<T: Loadable> Loadable for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T0: Loadable, T1: Loadable> Loadable for (T0, T1) {
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let (t0, len0) = T0::load(buffer)?;
|
||||
let (t1, len1) = T1::load(buffer)?;
|
||||
Ok((
|
||||
(t0, t1),
|
||||
len0 + len1
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Loadable, T1: Loadable, T2: Loadable> Loadable for (T0, T1, T2) {
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let (t0, len0) = T0::load(buffer)?;
|
||||
let (t1, len1) = T1::load(buffer)?;
|
||||
let (t2, len2) = T2::load(buffer)?;
|
||||
Ok((
|
||||
(t0, t1, t2),
|
||||
len0 + len1 + len2
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Loadable, T1: Loadable, T2: Loadable, T3: Loadable> Loadable for (T0, T1, T2, T3) {
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let (t0, len0) = T0::load(buffer)?;
|
||||
let (t1, len1) = T1::load(buffer)?;
|
||||
let (t2, len2) = T2::load(buffer)?;
|
||||
let (t3, len3) = T3::load(buffer)?;
|
||||
Ok((
|
||||
(t0, t1, t2, t3),
|
||||
len0 + len1 + len2 + len3
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: Loadable, T1: Loadable, T2: Loadable, T3: Loadable, T4: Loadable> Loadable for (T0, T1, T2, T3, T4) {
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let (t0, len0) = T0::load(buffer)?;
|
||||
let (t1, len1) = T1::load(buffer)?;
|
||||
let (t2, len2) = T2::load(buffer)?;
|
||||
let (t3, len3) = T3::load(buffer)?;
|
||||
let (t4, len4) = T4::load(buffer)?;
|
||||
Ok((
|
||||
(t0, t1, t2, t3, t4),
|
||||
len0 + len1 + len2 + len3 + len4
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Loadable for bool {
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut byte = [u8::MAX; 1];
|
||||
|
@ -121,6 +171,8 @@ mod tests {
|
|||
]
|
||||
}
|
||||
|
||||
test_impl! {tuple2_load_test, [0, 1], (u8, u8), 2, (0, 1)}
|
||||
|
||||
test_impl! {bool_true_load_test, [1], bool, 1, true}
|
||||
test_impl! {bool_false_load_test, [0], bool, 1, false}
|
||||
|
||||
|
|
|
@ -39,6 +39,12 @@ pub enum Packet {
|
|||
Bad,
|
||||
/// Many packets merged into one
|
||||
Many(Vec<Packet>),
|
||||
/// Translation data dump
|
||||
#[cfg(feature = "translate")]
|
||||
Translations(Vec<(String, Vec<String>)>),
|
||||
/// Request translations for language
|
||||
#[cfg(feature = "translate")]
|
||||
Language(String),
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
|
@ -53,6 +59,10 @@ impl Packet {
|
|||
Self::Unsupported => 6,
|
||||
Self::Bad => 7,
|
||||
Self::Many(_) => 8,
|
||||
#[cfg(feature = "translate")]
|
||||
Self::Translations(_) => 9,
|
||||
#[cfg(feature = "translate")]
|
||||
Self::Language(_) => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +92,17 @@ impl Loadable for Packet {
|
|||
8 => {
|
||||
let (obj, len) = <_>::load(buf)?;
|
||||
(Self::Many(obj), len)
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "translate")]
|
||||
9 => {
|
||||
let (obj, len) = <_>::load(buf)?;
|
||||
(Self::Translations(obj), len)
|
||||
},
|
||||
#[cfg(feature = "translate")]
|
||||
10 => {
|
||||
let (obj, len) = <_>::load(buf)?;
|
||||
(Self::Language(obj), len)
|
||||
},
|
||||
_ => return Err(LoadError::InvalidData),
|
||||
};
|
||||
result.1 += 1;
|
||||
|
@ -102,6 +122,10 @@ impl Dumpable for Packet {
|
|||
Self::Unsupported => Ok(0),
|
||||
Self::Bad => return Err(DumpError::Unsupported),
|
||||
Self::Many(v) => v.dump(buf),
|
||||
#[cfg(feature = "translate")]
|
||||
Self::Translations(tr) => tr.dump(buf),
|
||||
#[cfg(feature = "translate")]
|
||||
Self::Language(l) => l.dump(buf),
|
||||
}?;
|
||||
Ok(size1 + result)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "usdpl-front"
|
||||
version = "0.7.0"
|
||||
version = "0.9.0"
|
||||
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only"
|
||||
|
@ -12,11 +12,12 @@ description = "Universal Steam Deck Plugin Library front-end designed for WASM"
|
|||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["translate"]
|
||||
decky = ["usdpl-core/decky"]
|
||||
crankshaft = ["usdpl-core/crankshaft"]
|
||||
debug = ["console_error_panic_hook"]
|
||||
encrypt = ["usdpl-core/encrypt", "obfstr", "hex"]
|
||||
translate = ["usdpl-core/translate"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
|
@ -28,13 +29,6 @@ wasm-bindgen-futures = "0.4"
|
|||
# code size when deploying.
|
||||
console_error_panic_hook = { version = "0.1.6", optional = true }
|
||||
|
||||
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
|
||||
# compared to the default allocator's ~10K. It is slower than the default
|
||||
# allocator, however.
|
||||
#
|
||||
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
|
||||
wee_alloc = { version = "0.4.5", optional = true }
|
||||
|
||||
web-sys = { version = "0.3", features = [
|
||||
#'Headers',
|
||||
'Request',
|
||||
|
@ -48,7 +42,7 @@ js-sys = { version = "0.3" }
|
|||
obfstr = { version = "0.3", optional = true }
|
||||
hex = { version = "0.4", optional = true }
|
||||
|
||||
usdpl-core = { version = "0.6.0", path = "../usdpl-core" }
|
||||
usdpl-core = { version = "0.9.0", path = "../usdpl-core" }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = { version = "0.3.13" }
|
||||
|
|
|
@ -16,13 +16,14 @@ use usdpl_core::socket;
|
|||
#[cfg(feature = "encrypt")]
|
||||
const NONCE: [u8; socket::NONCE_SIZE]= [0u8; socket::NONCE_SIZE];
|
||||
|
||||
pub async fn send_js(
|
||||
pub async fn send_recv_packet(
|
||||
id: u64,
|
||||
packet: socket::Packet,
|
||||
port: u16,
|
||||
#[cfg(feature = "encrypt")]
|
||||
key: Vec<u8>,
|
||||
) -> Result<Vec<Primitive>, JsValue> {
|
||||
) -> Result<socket::Packet, JsValue> {
|
||||
|
||||
let mut opts = RequestInit::new();
|
||||
opts.method("POST");
|
||||
opts.mode(RequestMode::Cors);
|
||||
|
@ -53,34 +54,31 @@ pub async fn send_js(
|
|||
crate::imports::console_log(&format!("Received base64 `{}` len:{}", rust_str, rust_str.len()));
|
||||
|
||||
#[cfg(not(feature = "encrypt"))]
|
||||
match socket::Packet::load_base64(rust_str.as_bytes())
|
||||
{Ok(socket::Packet::load_base64(rust_str.as_bytes())
|
||||
.map_err(super::convert::str_to_js)?
|
||||
.0
|
||||
{
|
||||
socket::Packet::CallResponse(resp) => Ok(resp.response),
|
||||
_ => {
|
||||
//imports::console_warn(&format!("USDPL warning: Got non-call-response message from {}", resp.url()));
|
||||
Err(format!(
|
||||
"Expected call response message from {}, got something else",
|
||||
resp.url()
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
.0)}
|
||||
|
||||
#[cfg(feature = "encrypt")]
|
||||
match socket::Packet::load_encrypted(rust_str.as_bytes(), key.as_slice(), &NONCE)
|
||||
{Ok(socket::Packet::load_encrypted(rust_str.as_bytes(), key.as_slice(), &NONCE)
|
||||
.map_err(super::convert::str_to_js)?
|
||||
.0
|
||||
.0)}
|
||||
}
|
||||
|
||||
pub async fn send_call(
|
||||
id: u64,
|
||||
packet: socket::Packet,
|
||||
port: u16,
|
||||
#[cfg(feature = "encrypt")]
|
||||
key: Vec<u8>,
|
||||
) -> Result<Vec<Primitive>, JsValue> {
|
||||
let packet = send_recv_packet(id, packet, port, #[cfg(feature = "encrypt")] key).await?;
|
||||
|
||||
match packet
|
||||
{
|
||||
socket::Packet::CallResponse(resp) => Ok(resp.response),
|
||||
_ => {
|
||||
//imports::console_warn(&format!("USDPL warning: Got non-call-response message from {}", resp.url()));
|
||||
Err(format!(
|
||||
"Expected call response message from {}, got something else",
|
||||
resp.url()
|
||||
)
|
||||
.into())
|
||||
Err("Expected call response message, got something else".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,18 @@ use usdpl_core::{socket::Packet, RemoteCall};
|
|||
//const REMOTE_CALL_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
|
||||
//const REMOTE_PORT: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(31337);
|
||||
|
||||
static mut CTX: UsdplContext = UsdplContext { port: 31337, id: 1,
|
||||
#[cfg(feature = "encrypt")] key: Vec::new() };
|
||||
static mut CTX: UsdplContext = UsdplContext {
|
||||
port: 31337,
|
||||
id: 1,
|
||||
#[cfg(feature = "encrypt")]
|
||||
key: Vec::new(),
|
||||
};
|
||||
|
||||
static mut CACHE: Option<std::collections::HashMap<String, JsValue>> = None;
|
||||
|
||||
#[cfg(feature = "translate")]
|
||||
static mut TRANSLATIONS: Option<std::collections::HashMap<String, Vec<String>>> = None;
|
||||
|
||||
#[cfg(feature = "encrypt")]
|
||||
fn encryption_key() -> Vec<u8> {
|
||||
hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap()
|
||||
|
@ -52,11 +59,6 @@ fn increment_id() -> u64 {
|
|||
current_id
|
||||
}
|
||||
|
||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global allocator.
|
||||
#[cfg(feature = "wee_alloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
/// Initialize the front-end library
|
||||
#[wasm_bindgen]
|
||||
pub fn init_usdpl(port: u16) {
|
||||
|
@ -123,7 +125,7 @@ pub async fn call_backend(name: String, parameters: Vec<JsValue>) -> JsValue {
|
|||
let port = get_port();
|
||||
#[cfg(feature = "debug")]
|
||||
imports::console_log(&format!("USDPL: Got port {}", port));
|
||||
let results = connection::send_js(
|
||||
let results = connection::send_call(
|
||||
next_id,
|
||||
Packet::Call(RemoteCall {
|
||||
id: next_id,
|
||||
|
@ -152,3 +154,66 @@ pub async fn call_backend(name: String, parameters: Vec<JsValue>) -> JsValue {
|
|||
}
|
||||
results_js.into()
|
||||
}
|
||||
|
||||
/// Initialize translation strings for the front-end
|
||||
#[wasm_bindgen]
|
||||
pub async fn init_tr(locale: String) {
|
||||
let next_id = increment_id();
|
||||
match connection::send_recv_packet(
|
||||
next_id,
|
||||
Packet::Language(locale.clone()),
|
||||
get_port(),
|
||||
#[cfg(feature = "encrypt")]
|
||||
get_key()
|
||||
).await {
|
||||
Ok(Packet::Translations(translations)) => {
|
||||
#[cfg(feature = "debug")]
|
||||
imports::console_log(&format!("USDPL: Got translations for {}", locale));
|
||||
// convert translations into map
|
||||
let mut tr_map = std::collections::HashMap::with_capacity(translations.len());
|
||||
for (key, val) in translations {
|
||||
tr_map.insert(key, val);
|
||||
}
|
||||
unsafe { TRANSLATIONS = Some(tr_map) }
|
||||
},
|
||||
Ok(_) => {
|
||||
#[cfg(feature = "debug")]
|
||||
imports::console_error(&format!("USDPL: Got wrong packet response for init_tr"));
|
||||
unsafe { TRANSLATIONS = None }
|
||||
},
|
||||
#[allow(unused_variables)]
|
||||
Err(e) => {
|
||||
#[cfg(feature = "debug")]
|
||||
imports::console_error(&format!("USDPL: Got wrong error for init_tr: {}", e));
|
||||
unsafe { TRANSLATIONS = None }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Translate a phrase, equivalent to tr_n(msg_id, 0)
|
||||
#[wasm_bindgen]
|
||||
pub fn tr(msg_id: String) -> String {
|
||||
if let Some(translations) = unsafe { TRANSLATIONS.as_ref().unwrap().get(&msg_id) } {
|
||||
if let Some(translated) = translations.get(0) {
|
||||
translated.to_owned()
|
||||
} else {
|
||||
msg_id
|
||||
}
|
||||
} else {
|
||||
msg_id
|
||||
}
|
||||
}
|
||||
|
||||
/// Translate a phrase, retrieving the plural form for `n` items
|
||||
#[wasm_bindgen]
|
||||
pub fn tr_n(msg_id: String, n: usize) -> String {
|
||||
if let Some(translations) = unsafe { TRANSLATIONS.as_ref().unwrap().get(&msg_id) } {
|
||||
if let Some(translated) = translations.get(n) {
|
||||
translated.to_owned()
|
||||
} else {
|
||||
msg_id
|
||||
}
|
||||
} else {
|
||||
msg_id
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue