rt/boot.rs
1// boot -- what build_rs.py builds into a program, handed to the platform layer before the
2// program's own code runs
3//
4// Boot { app, manifest, assets } rt::main! fills it at compile time: JFGUI_APP (the app's
5// folder name), JFGUI_PERMISSIONS (apps/NAME/PERMISSIONS or
6// PERMISSIONS.<bin>), JFGUI_ASSETS (--cfg jfgui_assets, JFA1)
7// set_handler(f) (plat's process entry) f sets the program up: its name,
8// app://, its permissions
9// start(&boot) -> Result<(), i32> (rt::main!) the handler's verdict; Err = exit code. Without
10// a handler a manifest cannot be enforced: exit code 2
11//
12// rt knows nothing of plat; plat registers itself here, so console programs get the same
13// start-up as ui::main! without the UI crate.
14
15use crate::sync::SpinLock;
16
17/// what build_rs.py built into the program
18pub struct Boot {
19 /// the app's name for its folders (plat::vfs::set_app_id)
20 pub app: Option<&'static str>,
21 /// the app's permission manifest (plat::policy::install)
22 pub manifest: Option<&'static str>,
23 /// the app's assets, a JFA1 bundle (app://); empty without assets
24 pub assets: &'static [u8],
25}
26
27/// sets the program up -> Err(exit code)
28pub type Handler = fn(&Boot) -> Result<(), i32>;
29
30static HANDLER: SpinLock<Option<Handler>> = SpinLock::new(None);
31
32/// (plat's process entry) the function that sets a program up
33pub fn set_handler(f: Handler) {
34 *HANDLER.lock() = Some(f);
35}
36
37/// (rt::main!) set the program up before its own code runs
38pub fn start(b: &Boot) -> Result<(), i32> {
39 let h = *HANDLER.lock();
40 match h {
41 Some(f) => f(b),
42 None if b.manifest.is_some() => {
43 crate::os::write_stderr(b"error: no platform layer to install the permissions\n");
44 Err(2)
45 }
46 None => Ok(()),
47 }
48}