OXYGENHUB
◆ v0.1.9 oxygenhub-android / rust-core / src / lib.rs
4.3 KiB · Rust · last changed The phone runner says what it runs, on its card and notification (refs #8); pins OxygenFlow main 7 days ago source blame history raw
57c08243 Andy McCall ↶ 1
uniffi::setup_scaffolding!();
2
1dfa6314 Andy McCall ↶ 3
mod backdrop;
4
pub mod scenes;
5
4aee5293 Andy McCall ↶ 6
use std::path::Path;
7
8
// A simple test function to ensure the Kotlin <-> Rust bridge is working.
57c08243 Andy McCall ↶ 9
#[uniffi::export]
10
pub fn oxygen_greeting(name: String) -> String {
11
    format!("Hello, {}! Oxygen Native Core is active.", name)
4aee5293 Andy McCall ↶ 12
}
13
14
/// Why a runner call failed, in OxygenFlow's words.
15
#[derive(Debug, uniffi::Error)]
16
pub enum RunnerError {
17
    Failed { reason: String },
18
}
19
20
impl std::fmt::Display for RunnerError {
21
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22
        match self {
23
            RunnerError::Failed { reason } => f.write_str(reason),
24
        }
25
    }
26
}
27
28
impl std::error::Error for RunnerError {}
29
30
fn failed(e: anyhow::Error) -> RunnerError {
31
    RunnerError::Failed { reason: format!("{e:#}") }
32
}
33
34
/// The phone as an OxygenFlow runner (oxygenhub-android#8): OxygenFlow's
35
/// own runner, built into the app, offering only the WASM tier. `home` is
36
/// the app's directory for it; `register` keeps the runner's credential
37
/// there (runner.toml), as `flow runner register` does on a host.
38
#[uniffi::export]
39
pub fn runner_register(home: String, hub: String, token: String, name: String) -> Result<String, RunnerError> {
40
    let h = flow::home::Home::locate(Some(Path::new(&home))).map_err(failed)?;
41
    let r = flow::runner::register(&h, &hub, &token, &name, None, vec!["android".into()]).map_err(failed)?;
42
    Ok(r.name)
57c08243 Andy McCall ↶ 43
}
44
4aee5293 Andy McCall ↶ 45
/// Whether `home` holds a registration, and so can serve.
46
#[uniffi::export]
47
pub fn runner_is_registered(home: String) -> bool {
48
    Path::new(&home).join(flow::home::RUNNER_TOML).is_file()
49
}
50
51
/// Claim and run jobs until [`runner_stop`] drains the runner: returns
52
/// once the jobs it holds are done and reported. Blocks, so call it from
53
/// a thread of its own (the app's runner service).
54
#[uniffi::export]
55
pub fn runner_serve(home: String) -> Result<(), RunnerError> {
56
    let h = flow::home::Home::locate(Some(Path::new(&home))).map_err(failed)?;
74bbbc25 Andy McCall ↶ 57
    // An app has no HOME and runs in /, where oxy-core's clone would make
58
    // its own directory: keep it with the runner's.
59
    if std::env::var_os("OXY_HOME").is_none() {
60
        std::env::set_var("OXY_HOME", Path::new(&home).join("oxy"));
61
    }
4aee5293 Andy McCall ↶ 62
    flow::runner::serve_embedded(&h).map_err(failed)
63
}
64
65
/// Drain the runner: claim nothing more, finish and report what it
66
/// holds, then [`runner_serve`] returns. For leaving the charger or the
67
/// allowed network, or the owner stopping it.
68
#[uniffi::export]
69
pub fn runner_stop() {
70
    flow::runner::stop();
71
}
72
ed6c64d2 Andy McCall ↶ 73
/// Leave (oxygenflow#76): claim nothing more, and hand the jobs it holds
74
/// back to the hub, which gives them to another runner ahead of new work;
75
/// [`runner_serve`] then returns. With `notice_secs`, a job the hub expects
76
/// to finish within the notice finishes first (its checkpoint saved if
77
/// not). 0 for leaving the allowed network, where finishing would use the
78
/// network the owner ruled out; a minute for leaving the charger.
41e2e862 Andy McCall ↶ 79
#[uniffi::export]
ed6c64d2 Andy McCall ↶ 80
pub fn runner_leave(reason: String, notice_secs: u64) {
81
    flow::runner::leave_within(&reason, std::time::Duration::from_secs(notice_secs));
41e2e862 Andy McCall ↶ 82
}
83
4aee5293 Andy McCall ↶ 84
/// The tiers this phone offers (the WASM tier), and why not the others.
0b152017 Andy McCall ↶ 85
/// What the runner is running now: "owner/name #run job" for each job (#8).
4aee5293 Andy McCall ↶ 86
#[uniffi::export]
0b152017 Andy McCall ↶ 87
pub fn runner_running() -> Vec<String> {
88
    flow::runner::running()
89
}
90
91
#[uniffi::export]
4aee5293 Andy McCall ↶ 92
pub fn runner_tiers(home: String) -> Vec<String> {
93
    let Ok(h) = flow::home::Home::locate(Some(Path::new(&home))) else { return vec![] };
94
    match flow::runner::tiers(&h) {
95
        Ok((have, _)) => have,
96
        Err(_) => vec![],
97
    }
98
}
aa21eb5e Andy McCall ↶ 99
100
/// A new X25519 secret for this phone's alerts (#16), to keep wrapped by
101
/// the Android Keystore.
102
#[uniffi::export]
103
pub fn alert_new_secret() -> Vec<u8> {
104
    flow_core::alert::new_secret().to_vec()
105
}
106
107
/// The public key of an alert secret, for the hub; empty for a secret that
108
/// is not 32 bytes.
109
#[uniffi::export]
110
pub fn alert_public_key(secret: Vec<u8>) -> Vec<u8> {
111
    <[u8; 32]>::try_from(secret.as_slice()).map(|s| flow_core::alert::public_key(&s).to_vec()).unwrap_or_default()
112
}
113
114
/// Open an alert the hub sealed to this phone; `None` when it was not
115
/// sealed to `secret` or was changed on the way.
116
#[uniffi::export]
117
pub fn alert_open(secret: Vec<u8>, sealed: Vec<u8>) -> Option<Vec<u8>> {
118
    let s = <[u8; 32]>::try_from(secret.as_slice()).ok()?;
119
    flow_core::alert::open(&s, &sealed)
120
}