cvm-rs: version 0.2.0
- switch to napi-rs. this mostly affects only the backend side of things, but IMO napi-rs is better (also, way less boilerplate is needed compared to neon). - jpeg encoding no longer clones the input buffer internally (or wraps it in a Mutex as well), thanks to napi-rs not sucking in this regard. this is *probably* a micro-optimization, but will make it easier to later on do parallel encoding of all rectangles - guac encoding is weird. This is kind of a painpoint of napi-rs but it's bearable
This commit is contained in:
239
cvm-rs/Cargo.lock
generated
239
cvm-rs/Cargo.lock
generated
@@ -2,12 +2,57 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.99"
|
version = "1.0.99"
|
||||||
@@ -29,6 +74,15 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "convert_case"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -55,11 +109,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cvm-rs"
|
name = "ctor"
|
||||||
version = "0.1.1"
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cvm-rs"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"libc",
|
"libc",
|
||||||
"neon",
|
"napi",
|
||||||
|
"napi-build",
|
||||||
|
"napi-derive",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rayon",
|
"rayon",
|
||||||
"turbojpeg-sys",
|
"turbojpeg-sys",
|
||||||
@@ -72,15 +139,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "gimli"
|
||||||
version = "0.2.15"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
@@ -99,29 +161,86 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neon"
|
name = "memchr"
|
||||||
version = "1.0.0"
|
version = "2.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d75440242411c87dc39847b0e33e961ec1f10326a9d8ecf9c1ea64a3b3c13dc"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"adler",
|
||||||
"libloading",
|
|
||||||
"neon-macros",
|
|
||||||
"once_cell",
|
|
||||||
"semver",
|
|
||||||
"send_wrapper",
|
|
||||||
"smallvec",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neon-macros"
|
name = "napi"
|
||||||
version = "1.0.0"
|
version = "2.16.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6813fde79b646e47e7ad75f480aa80ef76a5d9599e2717407961531169ee38b"
|
checksum = "1277600d452e570cc83cf5f4e8efb389cc21e5cbefadcfba7239f4551e2e3e99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"ctor",
|
||||||
|
"napi-derive",
|
||||||
|
"napi-sys",
|
||||||
|
"once_cell",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "napi-build"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "napi-derive"
|
||||||
|
version = "2.16.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "150d87c4440b9f4815cb454918db498b5aae9a57aa743d20783fe75381181d01"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"convert_case",
|
||||||
|
"napi-derive-backend",
|
||||||
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
"syn-mid",
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "napi-derive-backend"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0cd81b794fc1d6051acf8c4f3cb4f82833b0621272a232b4ff0cf3df1dbddb61"
|
||||||
|
dependencies = [
|
||||||
|
"convert_case",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"semver",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "napi-sys"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3"
|
||||||
|
dependencies = [
|
||||||
|
"libloading",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.36.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -130,6 +249,12 @@ version = "1.19.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@@ -174,24 +299,47 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.23"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "send_wrapper"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.66"
|
version = "2.0.66"
|
||||||
@@ -204,14 +352,13 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn-mid"
|
name = "tokio"
|
||||||
version = "0.6.0"
|
version = "1.39.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049"
|
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"backtrace",
|
||||||
"quote",
|
"pin-project-lite",
|
||||||
"syn",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -233,10 +380,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "unicode-segmentation"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cvm-rs"
|
name = "cvm-rs"
|
||||||
description = "Rust utility library for cvmts. Runs all the high performance code"
|
description = "Rust utility library for cvmts. Runs all the high performance code"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
exclude = ["index.node"]
|
exclude = ["index.node"]
|
||||||
|
|
||||||
@@ -9,10 +9,17 @@ exclude = ["index.node"]
|
|||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
neon = "1"
|
|
||||||
libc = "0.2.155"
|
libc = "0.2.155"
|
||||||
|
|
||||||
# Required for JPEG
|
# Required for JPEG
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
turbojpeg-sys = "1.0.0"
|
turbojpeg-sys = "1.0.0"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
|
|
||||||
|
# node sex
|
||||||
|
napi = { version = "2.16.9", features = [ "async", "napi8", "error_anyhow" ] }
|
||||||
|
napi-derive = "2.16.11"
|
||||||
|
anyhow = "1.0.86"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
napi-build = "2.1.3"
|
||||||
|
|||||||
@@ -2,5 +2,11 @@
|
|||||||
import { createRequire } from 'module';
|
import { createRequire } from 'module';
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
export let {guacDecode, guacEncode, jpegEncode} = require('./index.node');
|
let {guacDecode, guacEncodeImpl, jpegEncode} = require('./index.node');
|
||||||
|
|
||||||
|
export { guacDecode, jpegEncode };
|
||||||
|
|
||||||
|
// shim for js->rust interop, because napi-rs kind of blows in this regard
|
||||||
|
export function guacEncode(...args) {
|
||||||
|
return guacEncodeImpl(args);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,47 +1,20 @@
|
|||||||
use crate::guac;
|
use crate::guac;
|
||||||
use neon::prelude::*;
|
|
||||||
|
|
||||||
fn guac_decode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsArray> {
|
use napi_derive::napi;
|
||||||
let input = cx.argument::<JsString>(0)?.value(cx);
|
|
||||||
|
|
||||||
|
#[napi(js_name = "guacDecode")]
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn guac_decode(input: String) -> napi::anyhow::Result<Vec<String>> {
|
||||||
match guac::decode_instruction(&input) {
|
match guac::decode_instruction(&input) {
|
||||||
Ok(data) => {
|
Ok(elements) => Ok(elements),
|
||||||
let array = JsArray::new(cx, data.len());
|
|
||||||
|
|
||||||
let conv = data
|
Err(err) => Err(anyhow::anyhow!("Error decoding Guacamole frame: {}", err)),
|
||||||
.iter()
|
|
||||||
.map(|v| cx.string(v))
|
|
||||||
.collect::<Vec<Handle<JsString>>>();
|
|
||||||
|
|
||||||
for (i, str) in conv.iter().enumerate() {
|
|
||||||
array.set(cx, i as u32, *str)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(e) => {
|
|
||||||
return cx.throw_error(format!("{}", e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guac_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsString> {
|
// ... this is ugly, but works
|
||||||
let mut elements: Vec<String> = Vec::with_capacity(cx.len());
|
#[napi(js_name = "guacEncodeImpl")]
|
||||||
|
#[allow(unused)]
|
||||||
// Capture varadic arguments
|
pub fn guac_encode(items: Vec<String>) -> napi::anyhow::Result<String> {
|
||||||
for i in 0..cx.len() {
|
Ok(guac::encode_instruction(&items))
|
||||||
let input = cx.argument::<JsString>(i)?.value(cx);
|
|
||||||
elements.push(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(cx.string(guac::encode_instruction(&elements)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn guac_decode(mut cx: FunctionContext) -> JsResult<JsArray> {
|
|
||||||
guac_decode_impl(&mut cx)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn guac_encode(mut cx: FunctionContext) -> JsResult<JsString> {
|
|
||||||
guac_encode_impl(&mut cx)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use napi::Env;
|
||||||
|
use napi_derive::napi;
|
||||||
use neon::prelude::*;
|
|
||||||
use neon::types::buffer::TypedArray;
|
|
||||||
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
@@ -12,23 +10,22 @@ use rayon::{ThreadPool, ThreadPoolBuilder};
|
|||||||
use crate::jpeg_compressor::*;
|
use crate::jpeg_compressor::*;
|
||||||
|
|
||||||
/// Gives a Rayon thread pool we use for parallelism
|
/// Gives a Rayon thread pool we use for parallelism
|
||||||
fn rayon_pool<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static ThreadPool> {
|
fn rayon_pool() -> &'static ThreadPool {
|
||||||
static RUNTIME: OnceCell<ThreadPool> = OnceCell::new();
|
static RUNTIME: OnceCell<ThreadPool> = OnceCell::new();
|
||||||
|
|
||||||
RUNTIME
|
RUNTIME.get_or_init(|| {
|
||||||
.get_or_try_init(|| {
|
// spawn at least 4 threads
|
||||||
// spawn at least 4 threads
|
let mut nr_threads = std::thread::available_parallelism().expect("??").get() / 8;
|
||||||
let mut nr_threads = std::thread::available_parallelism().expect("??").get() / 8;
|
if nr_threads == 0 {
|
||||||
if nr_threads == 0 {
|
nr_threads = 4;
|
||||||
nr_threads = 4;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ThreadPoolBuilder::new()
|
ThreadPoolBuilder::new()
|
||||||
.num_threads(nr_threads)
|
.num_threads(nr_threads)
|
||||||
.thread_name(|index| format!("cvmrs_jpeg_{}", index + 1))
|
.thread_name(|index| format!("cvmrs_jpeg_{}", index + 1))
|
||||||
.build()
|
.build()
|
||||||
})
|
.unwrap()
|
||||||
.or_else(|err| cx.throw_error(&err.to_string()))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@@ -38,43 +35,29 @@ thread_local! {
|
|||||||
// TODO: We should probably allow passing an array of images to encode, which would
|
// TODO: We should probably allow passing an array of images to encode, which would
|
||||||
// increase parallelism heavily.
|
// increase parallelism heavily.
|
||||||
|
|
||||||
fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise> {
|
#[napi(object)]
|
||||||
let input = cx.argument::<JsObject>(0)?;
|
pub struct JpegInputArgs {
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
pub stride: u32,
|
||||||
|
pub buffer: napi::JsBuffer,
|
||||||
|
}
|
||||||
|
|
||||||
// Get our input arguments here
|
#[napi(js_name = "jpegEncode")]
|
||||||
let width: u64 = input.get::<JsNumber, _, _>(cx, "width")?.value(cx) as u64;
|
#[allow(unused)]
|
||||||
let height: u64 = input.get::<JsNumber, _, _>(cx, "height")?.value(cx) as u64;
|
pub fn jpeg_encode(env: Env, input: JpegInputArgs) -> napi::Result<napi::JsObject> {
|
||||||
let stride: u64 = input.get::<JsNumber, _, _>(cx, "stride")?.value(cx) as u64;
|
let (deferred_resolver, promise) = env.create_deferred::<napi::JsUnknown, _>()?;
|
||||||
let buffer: Handle<JsBuffer> = input.get(cx, "buffer")?;
|
let buf = input.buffer.into_ref()?;
|
||||||
|
|
||||||
let (deferred, promise) = cx.promise();
|
|
||||||
let channel = cx.channel();
|
|
||||||
let pool = rayon_pool(cx)?;
|
|
||||||
|
|
||||||
let buf = buffer.as_slice(cx);
|
|
||||||
|
|
||||||
let copy: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(Vec::with_capacity(buf.len())));
|
|
||||||
|
|
||||||
// Copy from the node buffer to our temporary buffer
|
|
||||||
{
|
|
||||||
let mut locked = copy.lock().unwrap();
|
|
||||||
let cap = locked.capacity();
|
|
||||||
locked.resize(cap, 0);
|
|
||||||
locked.copy_from_slice(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn a task on the rayon pool that encodes the JPEG and fufills the promise
|
// Spawn a task on the rayon pool that encodes the JPEG and fufills the promise
|
||||||
// once it is done encoding.
|
// once it is done encoding.
|
||||||
pool.spawn_fifo(move || {
|
rayon_pool().spawn_fifo(move || {
|
||||||
let clone = Arc::clone(©);
|
|
||||||
let locked = clone.lock().unwrap();
|
|
||||||
|
|
||||||
let image: Image = Image {
|
let image: Image = Image {
|
||||||
buffer: locked.as_slice(),
|
buffer: &buf,
|
||||||
width: width as u32,
|
width: input.width as u32,
|
||||||
height: height as u32,
|
height: input.height as u32,
|
||||||
|
|
||||||
stride: (stride * 4u64) as u32, // I think?
|
stride: (input.stride as u64 * 4u64) as u32,
|
||||||
format: turbojpeg_sys::TJPF_TJPF_RGBA,
|
format: turbojpeg_sys::TJPF_TJPF_RGBA,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,18 +68,13 @@ fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise>
|
|||||||
b.compress_buffer(&image)
|
b.compress_buffer(&image)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fulfill the Javascript promise with our encoded buffer
|
deferred_resolver.resolve(move |env| {
|
||||||
deferred.settle_with(&channel, move |mut cx| {
|
let buffer = env
|
||||||
let mut buf = cx.buffer(vec.len())?;
|
.create_buffer_with_data(vec)
|
||||||
let slice = buf.as_mut_slice(&mut cx);
|
.expect("Couldn't create node Buffer, things are probably very broken by this point");
|
||||||
slice.copy_from_slice(vec.as_slice());
|
Ok(buffer.into_unknown())
|
||||||
Ok(buf)
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(promise)
|
Ok(promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jpeg_encode(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|
||||||
jpeg_encode_impl(&mut cx)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,15 +3,3 @@ mod guac_js;
|
|||||||
|
|
||||||
mod jpeg_compressor;
|
mod jpeg_compressor;
|
||||||
mod jpeg_js;
|
mod jpeg_js;
|
||||||
|
|
||||||
use neon::prelude::*;
|
|
||||||
|
|
||||||
#[neon::main]
|
|
||||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
|
||||||
// Mostly transitionary, later on API should change
|
|
||||||
cx.export_function("jpegEncode", jpeg_js::jpeg_encode)?;
|
|
||||||
|
|
||||||
cx.export_function("guacDecode", guac_js::guac_decode)?;
|
|
||||||
cx.export_function("guacEncode", guac_js::guac_encode)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user