portal_solutions_extism_compat/
lib.rs1use std::{collections::BTreeMap, sync::{LazyLock, Mutex}};
2
3use base64::Engine;
4use extism_pdk::*;
5#[link(wasm_import_module = "_ext")]
6unsafe extern "C" {
7 fn read_guest(id: u32, idx: u64) -> u8;
8 fn write_guest(id: u32, idx: u64, value: u8);
9 fn len_guest(id: u32) -> u64;
10}
11
12#[unsafe(export_name = "_px_app_core")]
13extern "C" fn core_call() {}
14
15pub static pollers: LazyLock<Mutex<BTreeMap<[u8; 32], ([u8; 32], String)>>> =
16 LazyLock::new(|| Mutex::new(Default::default()));
17
18pub fn do_login_poll(name: &str) -> Result<BTreeMap<[u8; 32], [u8; 32]>, Error> {
19 let mut p = pollers.lock().unwrap();
20 let mut m: BTreeMap<[u8; 32], [u8; 32]> = BTreeMap::new();
21 let mut blob = format!("");
22 let mut idxs = vec![];
23 for (k, (v, s)) in p.iter() {
24 if s != name {
25 continue;
26 }
27 blob = format!(
28 "{blob}${}",
29 base64::engine::general_purpose::URL_SAFE.encode(k)
30 );
31 idxs.push(*k);
32 }
34 let r = http::request::<Memory>(
35 &HttpRequest {
36 url: format!("{name}/login/auto/poll/b64/{blob}"),
37 headers: Default::default(),
38 method: Some(format!("GET")),
39 },
40 None,
41 )?;
42 for (c, k) in r.body().chunks(32).zip(idxs) {
43 let c: [u8; 32] = c.try_into().unwrap();
44 if c == [0u8; 32] {
45 continue;
46 }
47 let Some((v, _)) = p.remove(&k) else {
48 continue;
49 };
50 let v = std::array::from_fn(|i| c[i] ^ v[i]);
51 m.insert(k, v);
52 }
53 Ok(m)
54}