Skip to main content

Crate whisker_dev_server

Crate whisker_dev_server 

Source
Expand description

Host-side dev server for whisker run.

Owns the long-running dev loop: file watch, cargo rebuild, install to the device, subsecond patch construction, and WebSocket push. whisker-cli’s run subcommand is a thin wrapper that builds a Config and calls DevServer::run — every piece of UX-shaped logic lives here so future host shells (an editor plugin, a notebook, a remote-controlled CI build) can reuse it.

§Architecture

Constructed once via Config, the dev server spins up six cooperating pieces:

  • builder — translates Config into a whisker-build invocation (cargo + per-platform packaging) and runs it. Honours RUSTC_WORKSPACE_WRAPPER + linker shim env so the fat build doubles as a capture pass for Tier 1.
  • installer — for the cold-rebuild path: shells out to adb install / simctl install + launch. Identity (bundle id, applicationId, scheme, …) comes in flat via AndroidParams / IosParams; the cli resolves these from the user’s whisker.rs::configure(&mut Config). This crate never depends on whisker-config.
  • watchernotify-based, debounced, classifies events into ChangeKind::{RustCode, CargoToml, Other}.
  • serveraxum WebSocket endpoint at ws://<bind>/whisker-dev. Devices dial in, send a hello carrying their subsecond::aslr_reference(), then receive patch envelopes.
  • hotpatch — Tier 1 implementation. Builds a thin .o from the changed user crate via captured rustc args, links it into a patch dylib with a stub-object of host-symbol jumps, ships the resulting subsecond_types::JumpTable to connected clients.
  • lib.rs::run — the orchestrator: file event → decide_action (Tier 1 patch vs Tier 2 rebuild) → builder/hotpatch/sender.

§Layering

Stays manifest-agnostic on purpose. The cli does the whisker.rsConfig translation; this crate accepts only flat String / PathBuf fields. That keeps the dev-server reusable from any host shell that can produce the same flat Config (the cli is one; an editor plugin could be another).

Re-exports§

pub use builder::Builder;
pub use installer::Installer;
pub use server::Patch;
pub use server::PatchSender;
pub use watcher::Change;
pub use watcher::ChangeKind;
pub use workspace::discover_path_deps;
pub use workspace::identify_crate_for_paths;
pub use workspace::PathDepCrate;

Modules§

builder
Tier 2 cold rebuild: produce a fresh artifact + (re)install it on the active Target.
hotpatch
Tier 1 (subsecond) hot-reload pipeline.
installer
Tier 2 install + relaunch.
server
WebSocket dev server.
watcher
File watcher + change classifier for the dev loop.
workspace
Workspace path-dep walker.

Structs§

AndroidParams
Flat Android install/launch parameters. Populated by whisker-cli from the user’s whisker.rs::configure(&mut Config) plus a few hard defaults (jniLibs lives at <project_dir>/app/src/main/jniLibs, APK at <project_dir>/app/build/outputs/apk/debug/app-debug.apk, etc.). The dev-server never invents these values — if any are missing the cli is expected to error out before constructing Config.
CaptureShims
Shim wiring that turns a plain cargo invocation into a Tier 1 fat build. All paths are absolute; the dev-server creates the cache dirs on demand. real_linker is what the linker shim forwards to (typically the same cc/clang cargo would have used).
Config
Where the dev loop should run, what to build, and how to behave. Constructed by whisker-cli from CLI flags + the user’s whisker.rs (via the cli’s manifest/probe pipeline); or by an editor plugin / test harness directly.
DevServer
The dev loop. Construct with DevServer::new, then drive with DevServer::run (which returns when the server shuts down).
IosParams
Flat iOS Simulator install/launch parameters. Same pattern as AndroidParams — populated by the cli, consumed by the dev-server’s installer.

Enums§

Event
Observable events that bubble out of the dev loop. whisker-cli uses these to render terminal UI; an editor plugin would use them to drive its own UX.
HotPatchMode
How aggressive the dev loop is about reflecting edits.
LoopAction
Decision the change loop makes for one debounced change.
Target
What kind of binary the dev server is rebuilding.

Functions§

decide_action
Pure decision helper for the change loop. Tier 1 only handles ChangeKind::RustCode and only when a Patcher is available; Cargo.toml always needs a full rebuild because the dependency graph may have shifted; everything else is ignored.