use alloc::boxed::Box;
use wasefire_applet_api::fingerprint as api;
use wasefire_common::ptr::SharedPtr;
use wasefire_error::Error;
use crate::convert_unit;
#[cfg(feature = "api-fingerprint-matcher")]
pub mod matcher;
#[cfg(feature = "api-fingerprint-sensor")]
pub mod sensor;
pub trait Handler: 'static {
fn event(&self);
}
impl<F: Fn() + 'static> Handler for F {
fn event(&self) {
self()
}
}
#[must_use]
pub struct Listener<H: Handler> {
handler: SharedPtr<H>,
}
impl<H: Handler> Listener<H> {
pub fn new(handler: H) -> Result<Self, Error> {
let handler_func = Self::call;
let handler = Box::into_raw(Box::new(handler));
let handler_data = handler as *const u8;
let params = api::register::Params { handler_func, handler_data };
convert_unit(unsafe { api::register(params) })?;
Ok(Listener { handler: SharedPtr(handler) })
}
pub fn stop(self) {
core::mem::drop(self);
}
pub fn leak(self) {
core::mem::forget(self);
}
extern "C" fn call(data: *const u8) {
let handler = unsafe { &*(data as *const H) };
handler.event();
}
}
impl<H: Handler> Drop for Listener<H> {
fn drop(&mut self) {
convert_unit(unsafe { api::unregister() }).unwrap();
drop(unsafe { Box::from_raw(self.handler.0 as *mut H) });
}
}