Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7c9ccac175440d278fd129dbd53f04d66a6a6964
101 lines
2.7 KiB
Rust
101 lines
2.7 KiB
Rust
//! Media Stats UI - Pinakes plugin
|
|
//!
|
|
//! A UI-only plugin that adds a library statistics dashboard and a tag manager
|
|
//! page. All UI definitions live in `pages/stats.json` and
|
|
//! `pages/tag-manager.json`; this WASM binary provides the minimum lifecycle
|
|
//! surface the host runtime requires.
|
|
//!
|
|
//! This plugin is kind = ["ui_page"]: no media-type, metadata, thumbnail, or
|
|
//! event-handler extension points are needed. The host will never call them,
|
|
//! but exporting them avoids linker warnings if the host performs capability
|
|
//! discovery via symbol inspection.
|
|
|
|
#![no_std]
|
|
|
|
extern crate alloc;
|
|
|
|
use core::alloc::Layout;
|
|
|
|
#[global_allocator]
|
|
static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;
|
|
|
|
#[panic_handler]
|
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
|
core::arch::wasm32::unreachable()
|
|
}
|
|
|
|
// Host functions provided by the Pinakes runtime.
|
|
unsafe extern "C" {
|
|
// Write a result value back to the host (ptr + byte length).
|
|
fn host_set_result(ptr: i32, len: i32);
|
|
|
|
// Emit a structured log message to the host logger.
|
|
// `level` mirrors tracing severity: 0=trace 1=debug 2=info 3=warn 4=error
|
|
fn host_log(level: i32, ptr: i32, len: i32);
|
|
}
|
|
|
|
/// # Safety
|
|
///
|
|
/// `json` is a valid slice; the host copies the bytes before
|
|
/// returning so there are no lifetime concerns.
|
|
fn set_response(json: &[u8]) {
|
|
unsafe { host_set_result(json.as_ptr() as i32, json.len() as i32) }
|
|
}
|
|
|
|
/// # Safety
|
|
///
|
|
/// Same as [`set_response`]
|
|
fn log_info(msg: &[u8]) {
|
|
unsafe { host_log(2, msg.as_ptr() as i32, msg.len() as i32) }
|
|
}
|
|
|
|
/// Allocate a buffer for the host to write request data into.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// The byte offset of the allocation, or -1 on failure.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Size is positive; Layout construction cannot fail for align=1.
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn alloc(size: i32) -> i32 {
|
|
if size <= 0 {
|
|
return 0;
|
|
}
|
|
unsafe {
|
|
let layout = Layout::from_size_align_unchecked(size as usize, 1);
|
|
let ptr = alloc::alloc::alloc(layout);
|
|
if ptr.is_null() { -1 } else { ptr as i32 }
|
|
}
|
|
}
|
|
|
|
/// Called once after the plugin is loaded. Returns 0 on success.
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn initialize() -> i32 {
|
|
log_info(b"media-stats-ui: initialized");
|
|
0
|
|
}
|
|
|
|
/// Called before the plugin is unloaded. Returns 0 on success.
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn shutdown() -> i32 {
|
|
log_info(b"media-stats-ui: shutdown");
|
|
0
|
|
}
|
|
|
|
/// # Returns
|
|
///
|
|
/// an empty JSON array; this plugin adds no custom media types.
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn supported_media_types(_ptr: i32, _len: i32) {
|
|
set_response(b"[]");
|
|
}
|
|
|
|
/// # Returns
|
|
///
|
|
/// An empty JSON array; this plugin handles no event types.
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn interested_events(_ptr: i32, _len: i32) {
|
|
set_response(b"[]");
|
|
}
|