Skip to main content

lilo_rm_core/
launcher.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{RuntimeKind, SpawnRequest};
6
7#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub struct LaunchEnv {
9    pub key: String,
10    pub value: String,
11}
12
13impl LaunchEnv {
14    pub fn new(key: impl Into<String>, value: impl Into<String>) -> Self {
15        Self {
16            key: key.into(),
17            value: value.into(),
18        }
19    }
20}
21
22#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
23pub struct LaunchSpec {
24    pub argv: Vec<String>,
25    pub env: Vec<LaunchEnv>,
26    pub cwd: PathBuf,
27}
28
29impl LaunchSpec {
30    pub fn command(&self) -> Result<&str, LauncherError> {
31        self.argv
32            .first()
33            .map(String::as_str)
34            .ok_or(LauncherError::EmptyArgv)
35    }
36}
37
38pub trait RuntimeLauncher: Sync {
39    fn kind(&self) -> RuntimeKind;
40
41    fn argv(&self, request: &SpawnRequest) -> Result<Vec<String>, LauncherError>;
42
43    fn env(&self, request: &SpawnRequest) -> Result<Vec<LaunchEnv>, LauncherError>;
44
45    fn cwd(&self, request: &SpawnRequest) -> Result<PathBuf, LauncherError> {
46        Ok(request.cwd.clone())
47    }
48
49    fn launch_spec(&self, request: &SpawnRequest) -> Result<LaunchSpec, LauncherError> {
50        let spec = LaunchSpec {
51            argv: self.argv(request)?,
52            env: self.env(request)?,
53            cwd: self.cwd(request)?,
54        };
55        if spec.argv.is_empty() {
56            return Err(LauncherError::EmptyArgv);
57        }
58        if spec.env.is_empty() {
59            return Err(LauncherError::EmptyEnv {
60                runtime_kind: self.kind().to_string(),
61            });
62        }
63        Ok(spec)
64    }
65}
66
67#[derive(Clone, Debug, thiserror::Error)]
68pub enum LauncherError {
69    #[error("no launcher registered for runtime kind: {runtime_kind}")]
70    NoLauncher { runtime_kind: String },
71    #[error("launcher produced empty argv")]
72    EmptyArgv,
73    #[error("launcher {runtime_kind} produced empty env")]
74    EmptyEnv { runtime_kind: String },
75    #[error("failed to resolve launcher binary {binary}: {message}")]
76    BinaryLookupFailed { binary: String, message: String },
77}