use crate::{Handle, Obj, api, log, read_string};
use std::sync::OnceLock;
pub struct Bindings {
version: &'static str,
ok: OnceLock<bool>,
}
impl Bindings {
pub const fn new(version: &'static str) -> Bindings {
Bindings { version, ok: OnceLock::new() }
}
pub fn ok(&self) -> bool {
*self.ok.get_or_init(|| {
let running = read_string(|b, c| (api().ksa_version)(b, c));
let ok = running == self.version;
if !ok {
log(&format!("typed bindings were generated for another KSA build ({}, running {running}); regenerate them with `oxidizer --bindgen`", self.version));
}
ok
})
}
pub fn invoke(&self, this: Handle, token: i32, args: &[&Obj]) -> Obj {
if !self.ok() {
return Obj::NULL;
}
let hs: Vec<Handle> = args.iter().map(|a| a.handle()).collect();
unsafe { Obj::from_handle((api().invoke)(this, token, hs.as_ptr(), hs.len())) }
}
pub fn field_get(&self, this: Handle, token: i32) -> Obj {
if !self.ok() {
return Obj::NULL;
}
unsafe { Obj::from_handle((api().field_get)(this, token)) }
}
pub fn field_set(&self, this: Handle, token: i32, value: &Obj) {
if self.ok() {
(api().field_set)(this, token, value.handle());
}
}
}
pub fn to_f64(o: Obj) -> f64 {
o.f64().unwrap_or(f64::NAN)
}
pub fn to_i64(o: Obj) -> i64 {
o.i64().unwrap_or(0)
}
pub fn to_bool(o: Obj) -> bool {
o.f64().is_some_and(|v| v != 0.0)
}