use yog_abi::{YogBytes, YogHandlerFn, YogReply, YogStatus, status};
use yog_data::Schema;
use yog_event::Message;
use crate::registry::guard;
use crate::service::call_at;
#[doc(hidden)]
pub struct YogExportEntry {
pub name: &'static str,
pub handler: YogHandlerFn,
pub doc: &'static str,
pub shapes: fn() -> (yog_data::Shape, yog_data::Shape),
pub implements: &'static [&'static str],
}
#[doc(hidden)]
pub fn __yog_export_registry() -> &'static yog_sync::Mutex<Vec<YogExportEntry>> {
static REG: yog_sync::Mutex<Vec<YogExportEntry>> = yog_sync::Mutex::new(Vec::new());
®
}
pub fn export_address(mod_id: &str, name: &str) -> String {
yog_ids::join(mod_id, name)
}
#[doc(hidden)]
pub unsafe fn __yog_serve<A: Schema, R: Schema>(
payload: YogBytes,
reply: *const YogReply,
run: impl FnOnce(A) -> R,
) -> YogStatus {
let Some(args) = A::from_bytes(unsafe { payload.as_slice() }) else {
return status::BAD_PAYLOAD;
};
let Some(answer) = guard(None, || Some(run(args))) else {
return status::FAILED;
};
unsafe { YogReply::send(reply, &answer.to_bytes()) };
status::OK
}
pub fn call_export<A: Schema, R: Schema>(mod_id: &str, name: &str, args: &A) -> Option<R> {
R::from_bytes(&call_at(
yog_event::resolve(&export_address(mod_id, name)),
&args.to_bytes(),
)?)
}
impl crate::Registry {
#[doc(hidden)]
pub fn provide_export(&mut self, mod_id: &str, entry: &YogExportEntry) {
let address = export_address(mod_id, entry.name);
if self.provide_raw(&address, entry.handler) {
let (args, answer) = (entry.shapes)();
let interfaces = entry.implements.iter().map(|i| (*i).to_owned()).collect();
self.declare(&address, entry.doc, &args, &answer, interfaces);
}
}
}