pub const CONFIG_REGION_WASM_OFFSET: u32 = 0x24000;
pub const MAX_CONFIG_PARAMS: usize = 32;
#[derive(Clone, Copy)]
#[repr(C)]
pub struct ConfigRegion {
pub version: u8,
pub param_count: u8,
pub update_seq: u16,
pub _pad: [u8; 4],
pub update_ns: u64,
pub params: [i64; MAX_CONFIG_PARAMS],
pub types: [u8; MAX_CONFIG_PARAMS],
}
impl Default for ConfigRegion {
fn default() -> Self {
Self {
version: 1,
param_count: 0,
update_seq: 0,
_pad: [0; 4],
update_ns: 0,
params: [0; MAX_CONFIG_PARAMS],
types: [0; MAX_CONFIG_PARAMS],
}
}
}
pub mod ParamType {
pub const INT: u8 = 0;
pub const FLOAT: u8 = 1;
pub const BOOL: u8 = 2;
pub const BPS: u8 = 3;
}
impl ConfigRegion {
#[cfg(target_arch = "wasm32")]
#[inline(always)]
pub unsafe fn read() -> &'static Self {
&*(CONFIG_REGION_WASM_OFFSET as *const Self)
}
#[inline(always)]
pub fn get_i64(&self, slot: usize) -> i64 {
if slot < MAX_CONFIG_PARAMS { self.params[slot] } else { 0 }
}
#[inline(always)]
pub fn get_i32(&self, slot: usize) -> i32 {
self.get_i64(slot) as i32
}
#[inline(always)]
pub fn get_f64(&self, slot: usize) -> f64 {
f64::from_bits(self.get_i64(slot) as u64)
}
#[inline(always)]
pub fn get_bool(&self, slot: usize) -> bool {
self.get_i64(slot) != 0
}
#[inline(always)]
pub fn get_bps(&self, slot: usize) -> i32 {
self.get_i32(slot)
}
#[inline(always)]
pub fn is_updated(&self, last_seq: u16) -> bool {
self.update_seq != last_seq
}
#[inline(always)]
pub fn count(&self) -> usize {
self.param_count as usize
}
}
const _: () = assert!(
core::mem::size_of::<ConfigRegion>() == 304,
"ConfigRegion must be exactly 304 bytes"
);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn config_region_size() {
assert_eq!(core::mem::size_of::<ConfigRegion>(), 304);
}
#[test]
fn config_region_get_params() {
let mut config = ConfigRegion::default();
config.param_count = 3;
config.params[0] = 50; config.params[1] = 1_000_000_000; config.params[2] = f64::to_bits(0.5) as i64; config.types[0] = ParamType::BPS;
config.types[1] = ParamType::INT;
config.types[2] = ParamType::FLOAT;
assert_eq!(config.get_bps(0), 50);
assert_eq!(config.get_i64(1), 1_000_000_000);
assert!((config.get_f64(2) - 0.5).abs() < 0.001);
}
#[test]
fn config_region_update_detection() {
let mut config = ConfigRegion::default();
assert!(!config.is_updated(0));
config.update_seq = 1;
assert!(config.is_updated(0));
assert!(!config.is_updated(1));
}
#[test]
fn config_region_out_of_bounds() {
let config = ConfigRegion::default();
assert_eq!(config.get_i64(99), 0);
assert_eq!(config.get_i32(99), 0);
}
}