oxide_docs/lib.rs
1//! # Oxide — The Binary-First WebAssembly Browser
2//!
3//! <https://docs.oxide.foundation>
4//!
5//! Oxide is a **binary-first browser** that fetches and executes `.wasm`
6//! (WebAssembly) modules instead of HTML/JavaScript. Guest applications run
7//! in a secure sandbox with zero access to the host filesystem, environment
8//! variables, or raw network sockets. The browser exposes a rich set of
9//! **capability APIs** that guest modules import to interact with the host.
10//!
11//! The desktop shell is built on [GPUI](https://www.gpui.rs/) (Zed's
12//! GPU-accelerated UI framework). Guest draw commands map directly onto GPUI
13//! primitives — filled quads, GPU-shaped text, vector paths, and image
14//! textures — giving your canvas output full hardware acceleration.
15//!
16//! ## Crate Map
17//!
18//! | Crate | Purpose | Audience |
19//! |-------|---------|----------|
20//! | [`oxide_sdk`] | Guest SDK — safe Rust wrappers for the `"oxide"` host imports | App developers |
21//! | [`oxide_browser`] | Host runtime — Wasmtime engine, sandbox, GPUI shell | Browser contributors |
22//!
23//! ---
24//!
25//! # Quick Start — Building a Guest App
26//!
27//! ```toml
28//! # Cargo.toml
29//! [package]
30//! name = "my-oxide-app"
31//! version = "0.1.0"
32//! edition = "2021"
33//!
34//! [lib]
35//! crate-type = ["cdylib"]
36//!
37//! [dependencies]
38//! oxide-sdk = "0.6"
39//! ```
40//!
41//! ### Static app (one-shot render)
42//!
43//! ```rust,ignore
44//! use oxide_sdk::*;
45//!
46//! #[no_mangle]
47//! pub extern "C" fn start_app() {
48//! log("Hello from Oxide!");
49//! canvas_clear(30, 30, 46, 255);
50//! canvas_text(20.0, 40.0, 28.0, 255, 255, 255, 255, "Welcome to Oxide");
51//! }
52//! ```
53//!
54//! ### Interactive app (frame loop with widgets)
55//!
56//! ```rust,ignore
57//! use oxide_sdk::*;
58//!
59//! #[no_mangle]
60//! pub extern "C" fn start_app() { log("Ready"); }
61//!
62//! #[no_mangle]
63//! pub extern "C" fn on_frame(_dt_ms: u32) {
64//! canvas_clear(30, 30, 46, 255);
65//! let (mx, my) = mouse_position();
66//! canvas_circle(mx, my, 20.0, 255, 100, 100, 255);
67//! ui_button(1, 20.0, 20.0, 100.0, 30.0, "Click me!", || {
68//! log("Clicked!");
69//! });
70//! }
71//! ```
72//!
73//! ### High-level drawing API
74//!
75//! ```rust,ignore
76//! use oxide_sdk::draw::*;
77//!
78//! #[no_mangle]
79//! pub extern "C" fn start_app() {
80//! let c = Canvas::new();
81//! c.clear(Color::hex(0x1e1e2e));
82//! c.fill_rect(Rect::new(10.0, 10.0, 200.0, 100.0), Color::rgb(80, 120, 200));
83//! c.fill_circle(Point2D::new(300.0, 200.0), 50.0, Color::RED);
84//! c.text("Hello!", Point2D::new(20.0, 30.0), 24.0, Color::WHITE);
85//! }
86//! ```
87//!
88//! Build and run:
89//!
90//! ```bash
91//! cargo build --target wasm32-unknown-unknown --release
92//! # Open Oxide browser → navigate to your .wasm file
93//! ```
94//!
95//! ---
96//!
97//! # Architecture Overview
98//!
99//! ```text
100//! ┌─────────────────────────────────────────────────────┐
101//! │ Oxide Browser │
102//! │ │
103//! │ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
104//! │ │ URL Bar │ │ Canvas │ │ Console │ │
105//! │ └────┬─────┘ └──────┬─────┘ └──────┬───────────┘ │
106//! │ │ │ │ │
107//! │ ┌────▼───────────────▼───────────────▼──────────┐ │
108//! │ │ Host Runtime (oxide-browser) │ │
109//! │ │ Wasmtime engine · sandbox policy │ │
110//! │ │ fuel: 500M instructions · memory: 256 MB │ │
111//! │ └────────────────────┬──────────────────────────┘ │
112//! │ │ │
113//! │ ┌────────────────────▼──────────────────────────┐ │
114//! │ │ Capability Provider │ │
115//! │ │ "oxide" wasm import module │ │
116//! │ │ canvas · gpu · audio · video · capture │ │
117//! │ │ fetch · streaming · websocket · webrtc · midi │ │
118//! │ │ timers · animation frames · navigation │ │
119//! │ │ console · storage · clipboard · widgets │ │
120//! │ │ input · hyperlinks · crypto · protobuf │ │
121//! │ └────────────────────┬──────────────────────────┘ │
122//! │ │ │
123//! │ ┌────────────────────▼──────────────────────────┐ │
124//! │ │ Guest .wasm Module (oxide-sdk) │ │
125//! │ │ exports: start_app(), on_frame(dt_ms) │ │
126//! │ │ imports: oxide::* │ │
127//! │ └───────────────────────────────────────────────┘ │
128//! └─────────────────────────────────────────────────────┘
129//! ```
130//!
131//! ---
132//!
133//! # Guest SDK API Reference
134//!
135//! The [`oxide_sdk`] crate provides the full guest-side API. All functions
136//! are available via `use oxide_sdk::*;`.
137//!
138//! ## High-Level Drawing API (`oxide_sdk::draw`)
139//!
140//! The [`oxide_sdk::draw`] module provides GPUI-inspired ergonomic types
141//! that wrap the low-level canvas functions with less boilerplate:
142//!
143//! | Type | Description |
144//! |------|-------------|
145//! | [`oxide_sdk::draw::Color`] | sRGB + alpha with named constants and `hex()` constructor |
146//! | [`oxide_sdk::draw::Point2D`] | 2D point in canvas coordinates |
147//! | [`oxide_sdk::draw::Rect`] | Axis-aligned rectangle with hit-testing |
148//! | [`oxide_sdk::draw::Canvas`] | Zero-cost drawing facade |
149//!
150//! ```rust,ignore
151//! use oxide_sdk::draw::*;
152//!
153//! let c = Canvas::new();
154//! c.clear(Color::hex(0x1e1e2e));
155//! c.fill_rect(Rect::new(10.0, 10.0, 200.0, 100.0), Color::rgb(80, 120, 200));
156//! c.fill_circle(Point2D::new(300.0, 200.0), 50.0, Color::RED);
157//! c.text("Hello!", Point2D::new(20.0, 30.0), 24.0, Color::WHITE);
158//! c.line(Point2D::ZERO, Point2D::new(400.0, 300.0), 2.0, Color::YELLOW);
159//! let (w, h) = c.dimensions();
160//! ```
161//!
162//! ## Low-Level Canvas Drawing
163//!
164//! The canvas is the main rendering surface. Coordinates start at `(0, 0)`
165//! in the top-left corner. Each draw command maps to a GPUI GPU primitive.
166//!
167//! | Function | Description |
168//! |----------|-------------|
169//! | [`oxide_sdk::canvas_clear`] | Clear canvas with a solid RGBA color |
170//! | [`oxide_sdk::canvas_rect`] | Draw a filled rectangle |
171//! | [`oxide_sdk::canvas_circle`] | Draw a filled circle |
172//! | [`oxide_sdk::canvas_text`] | Draw text at a position |
173//! | [`oxide_sdk::canvas_line`] | Draw a line between two points |
174//! | [`oxide_sdk::canvas_dimensions`] | Get canvas `(width, height)` in pixels |
175//! | [`oxide_sdk::canvas_image`] | Draw an encoded image (PNG, JPEG, GIF, WebP) |
176//!
177//! ```rust,ignore
178//! use oxide_sdk::*;
179//!
180//! canvas_clear(30, 30, 46, 255);
181//! canvas_rect(10.0, 10.0, 200.0, 100.0, 80, 120, 200, 255);
182//! canvas_circle(300.0, 200.0, 50.0, 200, 100, 150, 255);
183//! canvas_text(20.0, 30.0, 24.0, 255, 255, 255, 255, "Hello!");
184//! canvas_line(0.0, 0.0, 400.0, 300.0, 255, 200, 0, 255, 2.0);
185//!
186//! let (w, h) = canvas_dimensions();
187//! log(&format!("Canvas: {}x{}", w, h));
188//! ```
189//!
190//! ## Console Logging
191//!
192//! | Function | Description |
193//! |----------|-------------|
194//! | [`oxide_sdk::log`] | Print an informational message |
195//! | [`oxide_sdk::warn`] | Print a warning (yellow) |
196//! | [`oxide_sdk::error`] | Print an error (red) |
197//!
198//! ## HTTP Networking
199//!
200//! All network access is mediated by the host — the guest never opens raw
201//! sockets. **Protocol Buffers** is the native wire format.
202//!
203//! | Function | Description |
204//! |----------|-------------|
205//! | [`oxide_sdk::fetch`] | Full HTTP request with method, headers, body |
206//! | [`oxide_sdk::fetch_get`] | HTTP GET shorthand |
207//! | [`oxide_sdk::fetch_post`] | HTTP POST with content-type and body |
208//! | [`oxide_sdk::fetch_post_proto`] | HTTP POST with protobuf body |
209//! | [`oxide_sdk::fetch_put`] | HTTP PUT |
210//! | [`oxide_sdk::fetch_delete`] | HTTP DELETE |
211//!
212//! ```rust,ignore
213//! use oxide_sdk::*;
214//!
215//! let resp = fetch_get("https://api.example.com/data").unwrap();
216//! log(&format!("Status: {}, Body: {}", resp.status, resp.text()));
217//! ```
218//!
219//! ## Protobuf — Native Data Format
220//!
221//! The [`oxide_sdk::proto`] module provides a zero-dependency protobuf
222//! encoder/decoder compatible with the Protocol Buffers wire format.
223//!
224//! ```rust,ignore
225//! use oxide_sdk::proto::{ProtoEncoder, ProtoDecoder};
226//!
227//! let msg = ProtoEncoder::new()
228//! .string(1, "alice")
229//! .uint64(2, 42)
230//! .bool(3, true)
231//! .finish();
232//!
233//! let mut decoder = ProtoDecoder::new(&msg);
234//! while let Some(field) = decoder.next() {
235//! match field.number {
236//! 1 => log(&format!("name = {}", field.as_str())),
237//! 2 => log(&format!("age = {}", field.as_u64())),
238//! _ => {}
239//! }
240//! }
241//! ```
242//!
243//! ## Storage
244//!
245//! Both stores are scoped to the app origin; session storage is cleared on
246//! cross-origin navigation, the KV store persists across restarts.
247//!
248//! | Function | Description |
249//! |----------|-------------|
250//! | [`oxide_sdk::storage_set`] | Store a key-value pair (session-scoped) |
251//! | [`oxide_sdk::storage_get`] | Retrieve a value by key |
252//! | [`oxide_sdk::storage_remove`] | Delete a key |
253//! | [`oxide_sdk::kv_store_set`] | Persistent on-disk KV store |
254//! | [`oxide_sdk::kv_store_get`] | Read from persistent KV store |
255//! | [`oxide_sdk::kv_store_delete`] | Delete from persistent KV store |
256//!
257//! ## Audio
258//!
259//! | Function | Description |
260//! |----------|-------------|
261//! | [`oxide_sdk::audio_play`] | Play audio from encoded bytes (WAV, MP3, OGG, FLAC) |
262//! | [`oxide_sdk::audio_play_url`] | Fetch audio from a URL and play it |
263//! | [`oxide_sdk::audio_play_with_format`] | Play with a format hint |
264//! | [`oxide_sdk::audio_detect_format`] | Sniff container from magic bytes |
265//! | [`oxide_sdk::audio_pause`] / [`oxide_sdk::audio_resume`] / [`oxide_sdk::audio_stop`] | Playback control |
266//! | [`oxide_sdk::audio_set_volume`] / [`oxide_sdk::audio_get_volume`] | Volume control (0.0 – 2.0) |
267//! | [`oxide_sdk::audio_is_playing`] | Check playback state |
268//! | [`oxide_sdk::audio_position`] / [`oxide_sdk::audio_seek`] / [`oxide_sdk::audio_duration`] | Seek and position |
269//! | [`oxide_sdk::audio_set_loop`] | Enable/disable looping |
270//! | [`oxide_sdk::audio_channel_play`] | Multi-channel simultaneous playback |
271//!
272//! ## Video
273//!
274//! Video decoding uses FFmpeg on the host. Frames are rendered as GPUI
275//! textures for GPU-accelerated compositing.
276//!
277//! | Function | Description |
278//! |----------|-------------|
279//! | [`oxide_sdk::video_load`] / [`oxide_sdk::video_load_url`] | Load video from bytes or URL |
280//! | [`oxide_sdk::video_play`] / [`oxide_sdk::video_pause`] / [`oxide_sdk::video_stop`] | Playback control |
281//! | [`oxide_sdk::video_render`] | Draw current frame to canvas rectangle |
282//! | [`oxide_sdk::video_seek`] / [`oxide_sdk::video_position`] / [`oxide_sdk::video_duration`] | Seek and timing |
283//! | [`oxide_sdk::video_set_volume`] / [`oxide_sdk::video_set_loop`] | Volume and looping |
284//! | [`oxide_sdk::video_set_pip`] | Picture-in-picture floating preview |
285//! | [`oxide_sdk::video_hls_variant_count`] / [`oxide_sdk::video_hls_open_variant`] | HLS adaptive streaming |
286//! | [`oxide_sdk::subtitle_load_srt`] / [`oxide_sdk::subtitle_load_vtt`] | Load subtitles |
287//!
288//! ## Media Capture
289//!
290//! Gated by the browser's per-origin permission prompt: the first call
291//! returns [`oxide_sdk::PERMISSION_PENDING`] while the prompt is showing —
292//! retry on a later frame. Apps shipping a manifest must declare these
293//! capabilities in `permissions` or calls are denied without prompting.
294//!
295//! | Function | Description |
296//! |----------|-------------|
297//! | [`oxide_sdk::camera_open`] / [`oxide_sdk::camera_close`] | Camera stream |
298//! | [`oxide_sdk::camera_capture_frame`] / [`oxide_sdk::camera_frame_dimensions`] | Capture RGBA8 frames |
299//! | [`oxide_sdk::microphone_open`] / [`oxide_sdk::microphone_close`] | Microphone stream |
300//! | [`oxide_sdk::microphone_read_samples`] / [`oxide_sdk::microphone_sample_rate`] | Read mono f32 samples |
301//! | [`oxide_sdk::screen_capture`] / [`oxide_sdk::screen_capture_dimensions`] | Screenshot |
302//!
303//! ## Timers
304//!
305//! Timer callbacks fire via the guest-exported `on_timer(callback_id)` function.
306//!
307//! | Function | Description |
308//! |----------|-------------|
309//! | [`oxide_sdk::set_timeout`] | One-shot timer after a delay |
310//! | [`oxide_sdk::set_interval`] | Repeating timer at an interval |
311//! | [`oxide_sdk::clear_timer`] | Cancel a timer |
312//! | [`oxide_sdk::time_now_ms`] | Current time (ms since UNIX epoch) |
313//!
314//! ## Animation Frames
315//!
316//! Vsync-aligned callbacks for smooth rendering. Callbacks fire via the
317//! guest-exported `on_timer(callback_id)` function (the same export used by
318//! [`oxide_sdk::set_timeout`]), one-shot per request.
319//!
320//! | Function | Description |
321//! |----------|-------------|
322//! | [`oxide_sdk::request_animation_frame`] | Schedule a one-shot frame callback |
323//! | [`oxide_sdk::cancel_animation_frame`] | Cancel a pending request |
324//!
325//! ## Streaming HTTP
326//!
327//! Non-blocking variant of [`oxide_sdk::fetch`] that streams the response body
328//! back to the guest in chunks. Returns immediately with a handle; poll
329//! [`oxide_sdk::fetch_state`] and [`oxide_sdk::fetch_recv`] each frame.
330//!
331//! | Function | Description |
332//! |----------|-------------|
333//! | [`oxide_sdk::fetch_begin`] | Dispatch a streaming request, returns a handle |
334//! | [`oxide_sdk::fetch_begin_get`] | GET shorthand |
335//! | [`oxide_sdk::fetch_state`] | Poll lifecycle state (`FETCH_*` constants) |
336//! | [`oxide_sdk::fetch_status`] | HTTP status code, or `0` until headers arrive |
337//! | [`oxide_sdk::fetch_recv`] | Poll the next body chunk as a [`oxide_sdk::FetchChunk`] |
338//! | [`oxide_sdk::fetch_recv_into`] | Poll into a caller-provided buffer (no allocation) |
339//! | [`oxide_sdk::fetch_error`] | Retrieve the error message for a failed request |
340//! | [`oxide_sdk::fetch_abort`] | Cancel an in-flight request |
341//!
342//! ## WebSocket
343//!
344//! Long-lived bidirectional connections. Messages are queued on the host and
345//! drained by the guest each frame via [`oxide_sdk::ws_recv`].
346//!
347//! | Function | Description |
348//! |----------|-------------|
349//! | [`oxide_sdk::ws_connect`] | Open a WebSocket, returns a handle |
350//! | [`oxide_sdk::ws_ready_state`] | Poll state ([`oxide_sdk::WS_OPEN`], etc.) |
351//! | [`oxide_sdk::ws_send_text`] | Send a UTF-8 text frame |
352//! | [`oxide_sdk::ws_send_binary`] | Send a binary frame |
353//! | [`oxide_sdk::ws_recv`] | Pop the next [`oxide_sdk::WsMessage`] from the queue |
354//! | [`oxide_sdk::ws_close`] | Initiate the close handshake |
355//! | [`oxide_sdk::ws_remove`] | Free host resources after close completes |
356//!
357//! ## MIDI Devices
358//!
359//! Read and write MIDI messages on hardware controllers and synthesisers.
360//! Each input port maintains a bounded queue; long SysEx packets are split.
361//!
362//! | Function | Description |
363//! |----------|-------------|
364//! | [`oxide_sdk::midi_input_count`] / [`oxide_sdk::midi_output_count`] | Enumerate ports |
365//! | [`oxide_sdk::midi_input_name`] / [`oxide_sdk::midi_output_name`] | Look up port names |
366//! | [`oxide_sdk::midi_open_input`] / [`oxide_sdk::midi_open_output`] | Open a port, returns a handle |
367//! | [`oxide_sdk::midi_send`] | Send raw MIDI bytes to an output |
368//! | [`oxide_sdk::midi_recv`] | Pop the next packet from an input queue |
369//! | [`oxide_sdk::midi_close`] | Close a port |
370//!
371//! ## GPU
372//!
373//! WebGPU-style API for GPU-backed buffers, textures, shaders, and
374//! pipelines. Shader source is WGSL.
375//!
376//! | Function | Description |
377//! |----------|-------------|
378//! | [`oxide_sdk::gpu_create_buffer`] | Allocate a GPU buffer |
379//! | [`oxide_sdk::gpu_create_texture`] | Allocate a 2D texture |
380//! | [`oxide_sdk::gpu_create_shader`] | Compile a WGSL shader module |
381//! | [`oxide_sdk::gpu_create_pipeline`] | Build a render pipeline |
382//! | [`oxide_sdk::gpu_create_compute_pipeline`] | Build a compute pipeline |
383//! | [`oxide_sdk::gpu_write_buffer`] | Upload bytes into a buffer |
384//! | [`oxide_sdk::gpu_draw`] | Issue a draw call into a target texture |
385//! | [`oxide_sdk::gpu_dispatch_compute`] | Dispatch a compute workgroup grid |
386//! | [`oxide_sdk::gpu_destroy_buffer`] / [`oxide_sdk::gpu_destroy_texture`] | Release GPU resources |
387//!
388//! ## Navigation & History
389//!
390//! | Function | Description |
391//! |----------|-------------|
392//! | [`oxide_sdk::navigate`] | Navigate to a new URL |
393//! | [`oxide_sdk::push_state`] | Push history entry (like `pushState()`) |
394//! | [`oxide_sdk::replace_state`] | Replace current history entry |
395//! | [`oxide_sdk::get_url`] | Get current page URL |
396//! | [`oxide_sdk::history_back`] / [`oxide_sdk::history_forward`] | Navigate history |
397//!
398//! ## Input Polling
399//!
400//! | Function | Description |
401//! |----------|-------------|
402//! | [`oxide_sdk::mouse_position`] | Mouse `(x, y)` in canvas coordinates |
403//! | [`oxide_sdk::mouse_button_down`] / [`oxide_sdk::mouse_button_clicked`] | Mouse button state |
404//! | [`oxide_sdk::key_down`] / [`oxide_sdk::key_pressed`] | Keyboard state |
405//! | [`oxide_sdk::scroll_delta`] | Scroll wheel delta |
406//! | [`oxide_sdk::shift_held`] / [`oxide_sdk::ctrl_held`] / [`oxide_sdk::alt_held`] | Modifier keys |
407//!
408//! ## Interactive Widgets
409//!
410//! Widgets are rendered during the `on_frame()` loop:
411//!
412//! | Function | Description |
413//! |----------|-------------|
414//! | [`oxide_sdk::ui_button`] | Clickable button, runs a callback when clicked |
415//! | [`oxide_sdk::ui_checkbox`] | Checkbox, returns current checked state |
416//! | [`oxide_sdk::ui_slider`] | Slider, returns current value |
417//! | [`oxide_sdk::ui_text_input`] | Text input field, returns current text |
418//!
419//! ## Crypto & Encoding
420//!
421//! | Function | Description |
422//! |----------|-------------|
423//! | [`oxide_sdk::hash_sha256`] | SHA-256 hash (32-byte array) |
424//! | [`oxide_sdk::hash_sha256_hex`] | SHA-256 hash (hex string) |
425//! | [`oxide_sdk::base64_encode`] / [`oxide_sdk::base64_decode`] | Base64 encoding/decoding |
426//!
427//! ## Other APIs
428//!
429//! | Function | Description |
430//! |----------|-------------|
431//! | [`oxide_sdk::clipboard_write`] / [`oxide_sdk::clipboard_read`] | System clipboard access |
432//! | [`oxide_sdk::random_u64`] / [`oxide_sdk::random_f64`] | Cryptographic random numbers |
433//! | [`oxide_sdk::notify`] | Send a notification |
434//! | [`oxide_sdk::upload_file`] | Open native file picker |
435//! | [`oxide_sdk::get_location`] | Mock geolocation |
436//! | [`oxide_sdk::load_module`] | Dynamically load another `.wasm` module |
437//! | [`oxide_sdk::register_hyperlink`] / [`oxide_sdk::clear_hyperlinks`] | Canvas hyperlinks |
438//! | [`oxide_sdk::url_resolve`] / [`oxide_sdk::url_encode`] / [`oxide_sdk::url_decode`] | URL utilities |
439//!
440//! ---
441//!
442//! # Browser Internals
443//!
444//! The [`oxide_browser`] crate contains the host-side implementation.
445//! Key modules for contributors:
446//!
447//! - **[`oxide_browser::engine`]** — Wasmtime engine setup, [`oxide_browser::engine::SandboxPolicy`],
448//! fuel metering, bounded linear memory
449//! - **[`oxide_browser::runtime`]** — [`oxide_browser::runtime::BrowserHost`] orchestrates module
450//! fetching, compilation, and execution. [`oxide_browser::runtime::LiveModule`] keeps interactive
451//! apps alive across frames.
452//! - **[`oxide_browser::capabilities`]** — The `"oxide"` import module: every host function the
453//! guest can call is registered here via `register_host_functions()`. Also contains shared state
454//! types ([`oxide_browser::capabilities::HostState`], [`oxide_browser::capabilities::CanvasState`],
455//! [`oxide_browser::capabilities::InputState`], etc.).
456//! - **[`oxide_browser::navigation`]** — [`oxide_browser::navigation::NavigationStack`] implements
457//! browser-style back/forward history with opaque state.
458//! - **[`oxide_browser::bookmarks`]** — [`oxide_browser::bookmarks::BookmarkStore`] provides
459//! persistent bookmark storage backed by sled.
460//! - **[`oxide_browser::url`]** — [`oxide_browser::url::OxideUrl`] wraps WHATWG URL parsing with
461//! support for `http`, `https`, `file`, and `oxide://` schemes.
462//! - **[`oxide_browser::ui`]** — [`oxide_browser::ui::OxideBrowserView`] and [`oxide_browser::ui::run_browser`]
463//! implement tabbed browsing, toolbar, canvas rendering, console panel, and bookmarks sidebar.
464//! - **[`oxide_browser::video`]**, **[`oxide_browser::audio_format`]**, **[`oxide_browser::media_capture`]** —
465//! FFmpeg video pipeline, audio format sniffing, and camera/microphone/screen capture host state.
466//! - **[`oxide_browser::gpu`]** — WebGPU-style host state: buffers, textures, shaders, and render/compute pipelines.
467//! - **[`oxide_browser::rtc`]** — WebRTC peer connections, data channels, media tracks, and the built-in signalling client.
468//! - **[`oxide_browser::websocket`]** — WebSocket host state: connection registry, send/recv queues, and ready-state tracking.
469//! - **[`oxide_browser::midi`]** — MIDI input/output port enumeration, bounded receive queues, and packet splitting.
470//! - **[`oxide_browser::fetch`]** — Streaming fetch host state: in-flight handles, body chunk queue, and abort tracking.
471//! - **[`oxide_browser::download`]** — Background downloader for non-WASM URLs surfaced as files in the host UI.
472//!
473//! ---
474//!
475//! # Guest Module Contract
476//!
477//! Every `.wasm` module loaded by Oxide must:
478//!
479//! 1. **Export `start_app`** — `extern "C" fn()` entry point called on load
480//! 2. **Optionally export `on_frame`** — `extern "C" fn(dt_ms: u32)` for
481//! interactive apps with a render loop
482//! 3. **Optionally export `on_timer`** — `extern "C" fn(callback_id: u32)`
483//! to receive timer callbacks
484//! 4. **Import from `"oxide"`** — all host APIs live under this namespace
485//! 5. **Compile as `cdylib`** — `crate-type = ["cdylib"]` in `Cargo.toml`
486//! 6. **Target `wasm32-unknown-unknown`** — no WASI, pure capability-based
487//!
488//! ---
489//!
490//! # Security Model
491//!
492//! | Constraint | Value | Purpose |
493//! |-----------|-------|---------|
494//! | Filesystem access | None | Guest cannot read/write host files |
495//! | Environment variables | None | Guest cannot inspect host env |
496//! | Raw network sockets | None | All networking is mediated via `fetch` |
497//! | Memory limit | 256 MB (4096 pages) | Prevents memory exhaustion |
498//! | Fuel limit | 500M instructions | Prevents infinite loops / DoS |
499//! | No WASI | — | Zero implicit system access |
500
501pub use oxide_browser;
502pub use oxide_sdk;