yog_api/messages/
interop.rs1use yog_abi::{YogBytes, YogHandlerFn, YogReply, YogStatus, status};
9use yog_data::Schema;
10use yog_event::Message;
11
12use crate::messages::service::call_at;
13use crate::mods::registry::guard;
14
15#[doc(hidden)]
17pub struct YogExportEntry {
18 pub name: &'static str,
19 pub handler: YogHandlerFn,
20 pub doc: &'static str,
22 pub shapes: fn() -> (yog_data::Shape, yog_data::Shape),
24 pub implements: &'static [&'static str],
26}
27
28#[doc(hidden)]
29pub fn __yog_export_registry() -> &'static yog_sync::Mutex<Vec<YogExportEntry>> {
30 static REG: yog_sync::Mutex<Vec<YogExportEntry>> = yog_sync::Mutex::new(Vec::new());
31 ®
32}
33
34pub fn export_address(mod_id: &str, name: &str) -> String {
36 yog_ids::join(mod_id, name)
37}
38
39#[doc(hidden)]
46pub unsafe fn __yog_serve<A: Schema, R: Schema>(
47 payload: YogBytes,
48 reply: *const YogReply,
49 run: impl FnOnce(A) -> R,
50) -> YogStatus {
51 let Some(args) = A::from_bytes(unsafe { payload.as_slice() }) else {
52 return status::BAD_PAYLOAD;
53 };
54 let Some(answer) = guard(None, || Some(run(args))) else {
55 return status::FAILED;
56 };
57 unsafe { YogReply::send(reply, &answer.to_bytes()) };
58 status::OK
59}
60
61pub fn call_export<A: Schema, R: Schema>(mod_id: &str, name: &str, args: &A) -> Option<R> {
64 R::from_bytes(&call_at(
65 yog_event::resolve(&export_address(mod_id, name)),
66 &args.to_bytes(),
67 )?)
68}
69
70impl crate::Registry {
71 #[doc(hidden)]
73 pub fn provide_export(&mut self, mod_id: &str, entry: &YogExportEntry) {
74 let address = export_address(mod_id, entry.name);
75 if self.provide_raw(&address, entry.handler) {
76 let (args, answer) = (entry.shapes)();
77 let interfaces = entry.implements.iter().map(|i| (*i).to_owned()).collect();
78 self.declare(&address, entry.doc, &args, &answer, interfaces);
79 }
80 }
81}