Skip to main content

tatara_vm/
engine.rs

1//! Engine selection — map a `(defvm …)` [`Hypervisor`] to an in-process
2//! [`maquina_engine::MaquinaEngine`].
3//!
4//! Only the Rust-native backends are real engines (zero shell-out): `Libkrun`
5//! (`tateru`) and `Kasou` (VZ). `Vfkit` / `VfkitDarwin` / `Qemu` are CLI
6//! emitters (the `vfkit` module) with no in-process engine — selecting them
7//! here is an error by design (see `theory/MAQUINA.md` § zero-shell-out).
8//!
9//! The real engines live behind tatara-vm's `engines` feature (macOS), which
10//! forwards to `maquina-engine`'s `tateru-backend` + `kasou-backend`. Without
11//! that feature (the default build, or any non-macOS target), `engine_for`
12//! reports the engine as unavailable so the host-agnostic build of tatara-vm
13//! stays dependency-light.
14
15// Gated with the dependency it names. `maquina-engine` is `optional = true`,
16// so an unconditional `use` here made the DEFAULT build fail with E0432
17// `unresolved import maquina_engine` — the exact opposite of this module's
18// stated purpose, which is to keep the featureless build dependency-light.
19#[cfg(all(target_os = "macos", feature = "engines"))]
20use maquina_engine::MaquinaEngine;
21
22use crate::config::Hypervisor;
23
24/// Why an engine could not be selected for a hypervisor.
25#[derive(Debug, thiserror::Error)]
26pub enum EngineSelectError {
27    /// The hypervisor is a CLI emitter, not an in-process engine.
28    #[error(
29        "hypervisor {0:?} has no in-process MaquinaEngine (it is a CLI emitter); \
30         select Libkrun or Kasou"
31    )]
32    NoEngine(Hypervisor),
33    /// No engine compiled in (engines are macOS-only, behind `--features engines`).
34    #[error("no máquina engine available: build tatara-vm with --features engines on macOS")]
35    Unavailable,
36}
37
38/// Select the in-process [`MaquinaEngine`] for a hypervisor.
39///
40/// # Errors
41/// [`EngineSelectError::NoEngine`] for shell-out hypervisors
42/// (`Vfkit`/`VfkitDarwin`/`Qemu`).
43#[cfg(all(target_os = "macos", feature = "engines"))]
44pub fn engine_for(h: &Hypervisor) -> Result<Box<dyn MaquinaEngine>, EngineSelectError> {
45    match h {
46        Hypervisor::Libkrun => Ok(Box::new(maquina_engine::tateru_backend::TateruEngine::new())),
47        Hypervisor::Kasou => Ok(Box::new(maquina_engine::kasou_backend::KasouEngine::new())),
48        other => Err(EngineSelectError::NoEngine(*other)),
49    }
50}
51
52/// Fallback when no engine backend is compiled in (default build / non-macOS).
53///
54/// The success type is [`std::convert::Infallible`] rather than
55/// `Box<dyn MaquinaEngine>`, and that is the honest signature: without the
56/// `engines` feature the `maquina-engine` crate is not linked at all, so there
57/// is no engine type to name — and no engine can ever be produced. An
58/// uninhabited `Ok` says exactly that at the type level instead of promising a
59/// value this build can never construct.
60///
61/// The previous signature named `MaquinaEngine` unconditionally, which is what
62/// forced the ungated `use` above and broke the default build.
63///
64/// # Errors
65/// Always [`EngineSelectError::Unavailable`].
66#[cfg(not(all(target_os = "macos", feature = "engines")))]
67pub fn engine_for(_h: &Hypervisor) -> Result<std::convert::Infallible, EngineSelectError> {
68    Err(EngineSelectError::Unavailable)
69}