@cloudglides/veil 0.1.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +103 -0
- package/dist/index.js +1000 -0
- package/dist/veil_core_bg.wasm +0 -0
- package/package.json +24 -10
- package/.envrc +0 -1
- package/.github/workflows/build-on-tag.yml +0 -82
- package/.github/workflows/deploy-pages.yml +0 -73
- package/example/index.html +0 -220
- package/example/veil_core.d.ts +0 -71
- package/example/veil_core_bg.wasm +0 -0
- package/example/veil_core_bg.wasm.d.ts +0 -20
- package/flake.nix +0 -68
- package/scripts/patch-wasm.js +0 -12
- package/src/cpu.ts +0 -67
- package/src/entropy/adblock.ts +0 -16
- package/src/entropy/approximate.ts +0 -9
- package/src/entropy/audio.ts +0 -17
- package/src/entropy/battery.ts +0 -10
- package/src/entropy/browser.ts +0 -7
- package/src/entropy/canvas.ts +0 -17
- package/src/entropy/complexity.ts +0 -14
- package/src/entropy/connection.ts +0 -14
- package/src/entropy/distribution.ts +0 -9
- package/src/entropy/fonts.ts +0 -4
- package/src/entropy/hardware.ts +0 -10
- package/src/entropy/language.ts +0 -14
- package/src/entropy/os.ts +0 -12
- package/src/entropy/osVersion.ts +0 -6
- package/src/entropy/performance.ts +0 -14
- package/src/entropy/permissions.ts +0 -15
- package/src/entropy/plugins.ts +0 -14
- package/src/entropy/preferences.ts +0 -12
- package/src/entropy/probabilistic.ts +0 -20
- package/src/entropy/screen.ts +0 -12
- package/src/entropy/screenInfo.ts +0 -8
- package/src/entropy/spectral.ts +0 -9
- package/src/entropy/statistical.ts +0 -15
- package/src/entropy/storage.ts +0 -22
- package/src/entropy/timezone.ts +0 -10
- package/src/entropy/userAgent.ts +0 -16
- package/src/entropy/webFeatures.ts +0 -21
- package/src/entropy/webgl.ts +0 -11
- package/src/gpu.ts +0 -132
- package/src/index.test.ts +0 -26
- package/src/index.ts +0 -248
- package/src/normalize/index.ts +0 -31
- package/src/probability.ts +0 -11
- package/src/scoring.ts +0 -106
- package/src/seeded-rng.ts +0 -14
- package/src/stability.ts +0 -405
- package/src/tamper.ts +0 -207
- package/src/types/index.ts +0 -11
- package/src/types.ts +0 -56
- package/src/veil_core.d.ts +0 -4
- package/src/wasm-loader.ts +0 -44
- package/tsconfig.json +0 -12
- package/tsup.config.ts +0 -41
- package/veil-core/Cargo.lock +0 -114
- package/veil-core/Cargo.toml +0 -12
- package/veil-core/src/entropy.rs +0 -132
- package/veil-core/src/lib.rs +0 -93
- package/veil-core/src/similarity.rs +0 -67
- package/vitest.config.ts +0 -15
- /package/{example → dist}/veil_core.js +0 -0
package/src/wasm-loader.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
let wasmInitialized = false;
|
|
2
|
-
let wasmModule: any = null;
|
|
3
|
-
|
|
4
|
-
async function loadWasmModule() {
|
|
5
|
-
if (wasmModule) return wasmModule;
|
|
6
|
-
|
|
7
|
-
const paths = [
|
|
8
|
-
() => import("./veil_core.js"),
|
|
9
|
-
() => import("../veil-core/pkg/veil_core.js"),
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
for (const pathFn of paths) {
|
|
13
|
-
try {
|
|
14
|
-
wasmModule = await pathFn();
|
|
15
|
-
return wasmModule;
|
|
16
|
-
} catch {
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
throw new Error("Failed to load WASM module from any location");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function initializeWasm() {
|
|
25
|
-
if (wasmInitialized) return;
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const wasm = await loadWasmModule();
|
|
29
|
-
if (typeof wasm.default === "function") {
|
|
30
|
-
await wasm.default();
|
|
31
|
-
}
|
|
32
|
-
wasmInitialized = true;
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.error("Failed to initialize WASM module:", error);
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function getWasmModule() {
|
|
40
|
-
if (!wasmInitialized) {
|
|
41
|
-
await initializeWasm();
|
|
42
|
-
}
|
|
43
|
-
return wasmModule;
|
|
44
|
-
}
|
package/tsconfig.json
DELETED
package/tsup.config.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsup";
|
|
2
|
-
import { cp, mkdir } from "fs/promises";
|
|
3
|
-
import { readFileSync, writeFileSync } from "fs";
|
|
4
|
-
import { resolve } from "path";
|
|
5
|
-
|
|
6
|
-
export default defineConfig({
|
|
7
|
-
entry: ["src/index.ts"],
|
|
8
|
-
format: ["esm"],
|
|
9
|
-
dts: true,
|
|
10
|
-
clean: true,
|
|
11
|
-
shims: true,
|
|
12
|
-
outDir: "dist",
|
|
13
|
-
external: ["./veil_core.js", "../veil-core/pkg/veil_core.js"],
|
|
14
|
-
noExternal: [],
|
|
15
|
-
splitting: true,
|
|
16
|
-
onSuccess: async () => {
|
|
17
|
-
const srcWasmDir = resolve("veil-core/pkg");
|
|
18
|
-
const distDir = resolve("dist");
|
|
19
|
-
const exampleDir = resolve("example");
|
|
20
|
-
|
|
21
|
-
await mkdir(distDir, { recursive: true });
|
|
22
|
-
await mkdir(exampleDir, { recursive: true });
|
|
23
|
-
|
|
24
|
-
for (const dir of [distDir, exampleDir]) {
|
|
25
|
-
await cp(`${srcWasmDir}/veil_core_bg.wasm`, `${dir}/veil_core_bg.wasm`);
|
|
26
|
-
await cp(`${srcWasmDir}/veil_core.js`, `${dir}/veil_core.js`);
|
|
27
|
-
await cp(`${srcWasmDir}/veil_core.d.ts`, `${dir}/veil_core.d.ts`);
|
|
28
|
-
await cp(
|
|
29
|
-
`${srcWasmDir}/veil_core_bg.wasm.d.ts`,
|
|
30
|
-
`${dir}/veil_core_bg.wasm.d.ts`,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
let wasmContent = readFileSync(`${dir}/veil_core.js`, "utf-8");
|
|
34
|
-
wasmContent = wasmContent.replace(
|
|
35
|
-
/module_or_path = new URL\('veil_core_bg\.wasm', import\.meta\.url\);/g,
|
|
36
|
-
"module_or_path = new URL('veil_core_bg.wasm', import.meta.url).href;",
|
|
37
|
-
);
|
|
38
|
-
writeFileSync(`${dir}/veil_core.js`, wasmContent);
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
});
|
package/veil-core/Cargo.lock
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# This file is automatically @generated by Cargo.
|
|
2
|
-
# It is not intended for manual editing.
|
|
3
|
-
version = 4
|
|
4
|
-
|
|
5
|
-
[[package]]
|
|
6
|
-
name = "bumpalo"
|
|
7
|
-
version = "3.19.1"
|
|
8
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
-
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
|
10
|
-
|
|
11
|
-
[[package]]
|
|
12
|
-
name = "cfg-if"
|
|
13
|
-
version = "1.0.4"
|
|
14
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
-
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
16
|
-
|
|
17
|
-
[[package]]
|
|
18
|
-
name = "once_cell"
|
|
19
|
-
version = "1.21.3"
|
|
20
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
-
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
|
22
|
-
|
|
23
|
-
[[package]]
|
|
24
|
-
name = "proc-macro2"
|
|
25
|
-
version = "1.0.103"
|
|
26
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
-
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
|
28
|
-
dependencies = [
|
|
29
|
-
"unicode-ident",
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
[[package]]
|
|
33
|
-
name = "quote"
|
|
34
|
-
version = "1.0.42"
|
|
35
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
-
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
|
37
|
-
dependencies = [
|
|
38
|
-
"proc-macro2",
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
[[package]]
|
|
42
|
-
name = "rustversion"
|
|
43
|
-
version = "1.0.22"
|
|
44
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
45
|
-
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
46
|
-
|
|
47
|
-
[[package]]
|
|
48
|
-
name = "syn"
|
|
49
|
-
version = "2.0.111"
|
|
50
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
-
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
|
52
|
-
dependencies = [
|
|
53
|
-
"proc-macro2",
|
|
54
|
-
"quote",
|
|
55
|
-
"unicode-ident",
|
|
56
|
-
]
|
|
57
|
-
|
|
58
|
-
[[package]]
|
|
59
|
-
name = "unicode-ident"
|
|
60
|
-
version = "1.0.22"
|
|
61
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
62
|
-
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
|
63
|
-
|
|
64
|
-
[[package]]
|
|
65
|
-
name = "veil-core"
|
|
66
|
-
version = "0.1.0"
|
|
67
|
-
dependencies = [
|
|
68
|
-
"wasm-bindgen",
|
|
69
|
-
]
|
|
70
|
-
|
|
71
|
-
[[package]]
|
|
72
|
-
name = "wasm-bindgen"
|
|
73
|
-
version = "0.2.106"
|
|
74
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
-
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
|
76
|
-
dependencies = [
|
|
77
|
-
"cfg-if",
|
|
78
|
-
"once_cell",
|
|
79
|
-
"rustversion",
|
|
80
|
-
"wasm-bindgen-macro",
|
|
81
|
-
"wasm-bindgen-shared",
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
[[package]]
|
|
85
|
-
name = "wasm-bindgen-macro"
|
|
86
|
-
version = "0.2.106"
|
|
87
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
88
|
-
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
|
89
|
-
dependencies = [
|
|
90
|
-
"quote",
|
|
91
|
-
"wasm-bindgen-macro-support",
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
[[package]]
|
|
95
|
-
name = "wasm-bindgen-macro-support"
|
|
96
|
-
version = "0.2.106"
|
|
97
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
98
|
-
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
|
99
|
-
dependencies = [
|
|
100
|
-
"bumpalo",
|
|
101
|
-
"proc-macro2",
|
|
102
|
-
"quote",
|
|
103
|
-
"syn",
|
|
104
|
-
"wasm-bindgen-shared",
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
[[package]]
|
|
108
|
-
name = "wasm-bindgen-shared"
|
|
109
|
-
version = "0.2.106"
|
|
110
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
111
|
-
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
|
112
|
-
dependencies = [
|
|
113
|
-
"unicode-ident",
|
|
114
|
-
]
|
package/veil-core/Cargo.toml
DELETED
package/veil-core/src/entropy.rs
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
#[allow(dead_code)]
|
|
2
|
-
pub fn kolmogorov_smirnov(values: &[f64]) -> f64 {
|
|
3
|
-
let mut sorted = values.to_vec();
|
|
4
|
-
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
|
5
|
-
|
|
6
|
-
let mut ks_statistic = 0.0;
|
|
7
|
-
for (i, &val) in sorted.iter().enumerate() {
|
|
8
|
-
let empirical_cdf = (i as f64 + 1.0) / sorted.len() as f64;
|
|
9
|
-
let theoretical_cdf = val;
|
|
10
|
-
let diff = (empirical_cdf - theoretical_cdf).abs();
|
|
11
|
-
if diff > ks_statistic {
|
|
12
|
-
ks_statistic = diff;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
ks_statistic
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
#[allow(dead_code)]
|
|
19
|
-
pub fn lempel_ziv_complexity(data: &[u8]) -> usize {
|
|
20
|
-
let mut complexity = 1;
|
|
21
|
-
let mut pointer = 0;
|
|
22
|
-
let mut window_size = 1;
|
|
23
|
-
|
|
24
|
-
while pointer + window_size < data.len() {
|
|
25
|
-
let window = &data[pointer..pointer + window_size];
|
|
26
|
-
let next = data[pointer + window_size];
|
|
27
|
-
|
|
28
|
-
let mut found = false;
|
|
29
|
-
for i in 0..pointer {
|
|
30
|
-
if i + window_size < data.len()
|
|
31
|
-
&& &data[i..i + window_size] == window
|
|
32
|
-
&& data.get(i + window_size) == Some(&next)
|
|
33
|
-
{
|
|
34
|
-
found = true;
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if !found {
|
|
39
|
-
complexity += 1;
|
|
40
|
-
pointer += window_size;
|
|
41
|
-
window_size = 1;
|
|
42
|
-
} else {
|
|
43
|
-
window_size += 1;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
complexity
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
#[allow(dead_code)]
|
|
50
|
-
pub fn spectral_entropy(samples: &[f64]) -> f64 {
|
|
51
|
-
let n = samples.len();
|
|
52
|
-
let mut real = vec![0.0; n];
|
|
53
|
-
let mut imag = vec![0.0; n];
|
|
54
|
-
|
|
55
|
-
for k in 0..n {
|
|
56
|
-
for (n_idx, &sample) in samples.iter().enumerate() {
|
|
57
|
-
let angle = -2.0 * std::f64::consts::PI * (k as f64) * (n_idx as f64) / (n as f64);
|
|
58
|
-
real[k] += sample * angle.cos();
|
|
59
|
-
imag[k] += sample * angle.sin();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let mut power: Vec<f64> = real
|
|
64
|
-
.iter()
|
|
65
|
-
.zip(imag.iter())
|
|
66
|
-
.map(|(r, i)| (r * r + i * i).sqrt())
|
|
67
|
-
.collect();
|
|
68
|
-
|
|
69
|
-
let total_power: f64 = power.iter().sum();
|
|
70
|
-
|
|
71
|
-
let mut entropy = 0.0;
|
|
72
|
-
for p in power.iter_mut() {
|
|
73
|
-
if *p > 0.0 {
|
|
74
|
-
*p /= total_power;
|
|
75
|
-
entropy -= *p * p.log2();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
entropy
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
#[allow(dead_code)]
|
|
82
|
-
pub fn approximate_entropy(samples: &[f64], m: usize) -> f64 {
|
|
83
|
-
fn count_matches(data: &[f64], m: usize) -> usize {
|
|
84
|
-
let mut count = 0;
|
|
85
|
-
for i in 0..=(data.len().saturating_sub(m)) {
|
|
86
|
-
for j in (i + 1)..=(data.len().saturating_sub(m)) {
|
|
87
|
-
let mut match_found = true;
|
|
88
|
-
for k in 0..m {
|
|
89
|
-
if (data[i + k] - data[j + k]).abs() > 0.001 {
|
|
90
|
-
match_found = false;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if match_found {
|
|
95
|
-
count += 1;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
count
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
let c1 = (count_matches(samples, m) as f64 + 1.0) / (samples.len() as f64 - m as f64 + 1.0);
|
|
103
|
-
let c2 = (count_matches(samples, m + 1) as f64 + 1.0) / (samples.len() as f64 - m as f64);
|
|
104
|
-
(c1 / c2).ln()
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
#[allow(dead_code)]
|
|
108
|
-
pub fn sample_entropy(samples: &[f64], m: usize, r: f64) -> f64 {
|
|
109
|
-
fn count_template_matches(data: &[f64], m: usize, r: f64) -> usize {
|
|
110
|
-
let mut count = 0;
|
|
111
|
-
for i in 0..=(data.len().saturating_sub(m)) {
|
|
112
|
-
for j in (i + 1)..=(data.len().saturating_sub(m)) {
|
|
113
|
-
let mut max_diff = 0.0;
|
|
114
|
-
for k in 0..m {
|
|
115
|
-
let diff = (data[i + k] - data[j + k]).abs();
|
|
116
|
-
if diff > max_diff {
|
|
117
|
-
max_diff = diff;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if max_diff < r {
|
|
121
|
-
count += 1;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
count
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let c1 = count_template_matches(samples, m, r) as f64;
|
|
129
|
-
let c2 = count_template_matches(samples, m + 1, r) as f64;
|
|
130
|
-
|
|
131
|
-
if c2 > 0.0 { -(c1 / c2).ln() } else { 0.0 }
|
|
132
|
-
}
|
package/veil-core/src/lib.rs
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
use std::usize;
|
|
2
|
-
|
|
3
|
-
use wasm_bindgen::prelude::*;
|
|
4
|
-
|
|
5
|
-
mod entropy;
|
|
6
|
-
mod similarity;
|
|
7
|
-
|
|
8
|
-
const MURMUR_SEED: u32 = 0x811c9dc5;
|
|
9
|
-
const FNV_PRIME: u32 = 16777619;
|
|
10
|
-
const FNV_OFFSET_BASIS: u32 = 2166136261;
|
|
11
|
-
|
|
12
|
-
#[wasm_bindgen]
|
|
13
|
-
pub fn murmur_hash(s: &str) -> String {
|
|
14
|
-
let mut h1 = MURMUR_SEED;
|
|
15
|
-
for byte in s.as_bytes() {
|
|
16
|
-
h1 ^= *byte as u32;
|
|
17
|
-
h1 = h1
|
|
18
|
-
.wrapping_add(h1 << 1)
|
|
19
|
-
.wrapping_add(h1 << 4)
|
|
20
|
-
.wrapping_add(h1 << 7)
|
|
21
|
-
.wrapping_add(h1 << 8)
|
|
22
|
-
.wrapping_add(h1 << 24);
|
|
23
|
-
}
|
|
24
|
-
format!("{:x}", h1)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
#[wasm_bindgen]
|
|
28
|
-
pub fn fnv_hash(s: &str) -> String {
|
|
29
|
-
let mut hash = FNV_OFFSET_BASIS;
|
|
30
|
-
for byte in s.as_bytes() {
|
|
31
|
-
hash ^= *byte as u32;
|
|
32
|
-
hash = hash.wrapping_mul(FNV_PRIME);
|
|
33
|
-
}
|
|
34
|
-
format!("{:x}", hash)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
#[wasm_bindgen]
|
|
38
|
-
pub fn shannon_entropy(s: &str) -> f64 {
|
|
39
|
-
let mut freq = [0usize; 256];
|
|
40
|
-
for byte in s.as_bytes() {
|
|
41
|
-
freq[*byte as usize] += 1;
|
|
42
|
-
}
|
|
43
|
-
let len = s.len() as f64;
|
|
44
|
-
let mut entropy = 0.0;
|
|
45
|
-
|
|
46
|
-
for &count in &freq {
|
|
47
|
-
if count > 0 {
|
|
48
|
-
let p = count as f64 / len;
|
|
49
|
-
entropy -= p * p.log2();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
entropy
|
|
53
|
-
}
|
|
54
|
-
#[wasm_bindgen]
|
|
55
|
-
pub fn kolmogorov_complexity(s: &str) -> f64 {
|
|
56
|
-
let len = s.len();
|
|
57
|
-
let mut runs = 0;
|
|
58
|
-
let bytes = s.as_bytes();
|
|
59
|
-
|
|
60
|
-
for i in 1..bytes.len() {
|
|
61
|
-
if bytes[i] != bytes[i - 1] {
|
|
62
|
-
runs += 1;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
(len as f64) + (len as f64 * (runs as f64 / len as f64))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#[wasm_bindgen]
|
|
69
|
-
pub fn ks_test(values: &[f64]) -> f64 {
|
|
70
|
-
entropy::kolmogorov_smirnov(values)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
#[wasm_bindgen]
|
|
74
|
-
pub fn lz_complexity(data: &[u8]) -> usize {
|
|
75
|
-
entropy::lempel_ziv_complexity(data)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
#[wasm_bindgen]
|
|
79
|
-
pub fn spectral(samples: &[f64]) -> f64 {
|
|
80
|
-
entropy::spectral_entropy(samples)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
#[wasm_bindgen]
|
|
84
|
-
pub fn approx_entropy(samples: &[f64], m: usize) -> f64 {
|
|
85
|
-
entropy::approximate_entropy(samples, m)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
#[wasm_bindgen]
|
|
89
|
-
pub fn sample_ent(samples: &[f64], m: usize, r: f64) -> f64 {
|
|
90
|
-
entropy::sample_entropy(samples, m, r)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
pub use similarity::{levenshtein_distance, similarity_score, cosine_similarity};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
pub use wasm_bindgen::prelude::*;
|
|
2
|
-
|
|
3
|
-
#[wasm_bindgen]
|
|
4
|
-
pub fn levenshtein_distance(s1: &str, s2: &str) -> u32 {
|
|
5
|
-
let len1 = s1.len();
|
|
6
|
-
let len2 = s2.len();
|
|
7
|
-
let mut matrix = vec![vec![0u32; len2 + 1]; len1 + 1];
|
|
8
|
-
|
|
9
|
-
for i in 0..=len1 {
|
|
10
|
-
matrix[i][0] = i as u32;
|
|
11
|
-
}
|
|
12
|
-
for j in 0..=len2 {
|
|
13
|
-
matrix[0][j] = j as u32;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let bytes1 = s1.as_bytes();
|
|
17
|
-
let bytes2 = s2.as_bytes();
|
|
18
|
-
|
|
19
|
-
for i in 1..=len1 {
|
|
20
|
-
for j in 1..=len2 {
|
|
21
|
-
let cost = if bytes1[i - 1] == bytes2[j - 1] { 0 } else { 1 };
|
|
22
|
-
matrix[i][j] = std::cmp::min(
|
|
23
|
-
std::cmp::min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1),
|
|
24
|
-
matrix[i - 1][j - 1] + cost,
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
matrix[len1][len2]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
#[wasm_bindgen]
|
|
33
|
-
pub fn similarity_score(s1: &str, s2: &str) -> f64 {
|
|
34
|
-
let distance = levenshtein_distance(s1, s2) as f64;
|
|
35
|
-
let max_len = std::cmp::max(s1.len(), s2.len()) as f64;
|
|
36
|
-
if max_len == 0.0 {
|
|
37
|
-
1.0
|
|
38
|
-
} else {
|
|
39
|
-
1.0 - (distance / max_len)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
#[wasm_bindgen]
|
|
44
|
-
pub fn cosine_similarity(v1: &[f64], v2: &[f64]) -> f64 {
|
|
45
|
-
if v1.len() != v2.len() || v1.is_empty() {
|
|
46
|
-
return 0.0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let mut dot = 0.0;
|
|
50
|
-
let mut mag1 = 0.0;
|
|
51
|
-
let mut mag2 = 0.0;
|
|
52
|
-
|
|
53
|
-
for i in 0..v1.len() {
|
|
54
|
-
dot += v1[i] * v2[i];
|
|
55
|
-
mag1 += v1[i] * v1[i];
|
|
56
|
-
mag2 += v2[i] * v2[i];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
mag1 = mag1.sqrt();
|
|
60
|
-
mag2 = mag2.sqrt();
|
|
61
|
-
|
|
62
|
-
if mag1 == 0.0 || mag2 == 0.0 {
|
|
63
|
-
0.0
|
|
64
|
-
} else {
|
|
65
|
-
dot / (mag1 * mag2)
|
|
66
|
-
}
|
|
67
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
import wasm from "vite-plugin-wasm";
|
|
3
|
-
import topLevelAwait from "vite-plugin-top-level-await";
|
|
4
|
-
|
|
5
|
-
export default defineConfig({
|
|
6
|
-
plugins: [wasm(), topLevelAwait()],
|
|
7
|
-
test: {
|
|
8
|
-
environment: "happy-dom",
|
|
9
|
-
globals: true,
|
|
10
|
-
exclude: ["node_modules", "dist", ".direnv"],
|
|
11
|
-
},
|
|
12
|
-
optimizeDeps: {
|
|
13
|
-
exclude: ["veil-core"],
|
|
14
|
-
},
|
|
15
|
-
});
|
|
File without changes
|