Skip to main content

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//!     if 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//! | Function | Description |
246//! |----------|-------------|
247//! | [`oxide_sdk::storage_set`] | Store a key-value pair (session-scoped) |
248//! | [`oxide_sdk::storage_get`] | Retrieve a value by key |
249//! | [`oxide_sdk::storage_remove`] | Delete a key |
250//! | [`oxide_sdk::kv_store_set`] | Persistent on-disk KV store |
251//! | [`oxide_sdk::kv_store_get`] | Read from persistent KV store |
252//! | [`oxide_sdk::kv_store_delete`] | Delete from persistent KV store |
253//!
254//! ## Audio
255//!
256//! | Function | Description |
257//! |----------|-------------|
258//! | [`oxide_sdk::audio_play`] | Play audio from encoded bytes (WAV, MP3, OGG, FLAC) |
259//! | [`oxide_sdk::audio_play_url`] | Fetch audio from a URL and play it |
260//! | [`oxide_sdk::audio_play_with_format`] | Play with a format hint |
261//! | [`oxide_sdk::audio_detect_format`] | Sniff container from magic bytes |
262//! | [`oxide_sdk::audio_pause`] / [`oxide_sdk::audio_resume`] / [`oxide_sdk::audio_stop`] | Playback control |
263//! | [`oxide_sdk::audio_set_volume`] / [`oxide_sdk::audio_get_volume`] | Volume control (0.0 – 2.0) |
264//! | [`oxide_sdk::audio_is_playing`] | Check playback state |
265//! | [`oxide_sdk::audio_position`] / [`oxide_sdk::audio_seek`] / [`oxide_sdk::audio_duration`] | Seek and position |
266//! | [`oxide_sdk::audio_set_loop`] | Enable/disable looping |
267//! | [`oxide_sdk::audio_channel_play`] | Multi-channel simultaneous playback |
268//!
269//! ## Video
270//!
271//! Video decoding uses FFmpeg on the host. Frames are rendered as GPUI
272//! textures for GPU-accelerated compositing.
273//!
274//! | Function | Description |
275//! |----------|-------------|
276//! | [`oxide_sdk::video_load`] / [`oxide_sdk::video_load_url`] | Load video from bytes or URL |
277//! | [`oxide_sdk::video_play`] / [`oxide_sdk::video_pause`] / [`oxide_sdk::video_stop`] | Playback control |
278//! | [`oxide_sdk::video_render`] | Draw current frame to canvas rectangle |
279//! | [`oxide_sdk::video_seek`] / [`oxide_sdk::video_position`] / [`oxide_sdk::video_duration`] | Seek and timing |
280//! | [`oxide_sdk::video_set_volume`] / [`oxide_sdk::video_set_loop`] | Volume and looping |
281//! | [`oxide_sdk::video_set_pip`] | Picture-in-picture floating preview |
282//! | [`oxide_sdk::video_hls_variant_count`] / [`oxide_sdk::video_hls_open_variant`] | HLS adaptive streaming |
283//! | [`oxide_sdk::subtitle_load_srt`] / [`oxide_sdk::subtitle_load_vtt`] | Load subtitles |
284//!
285//! ## Media Capture
286//!
287//! The host shows permission dialogs before granting access to hardware.
288//!
289//! | Function | Description |
290//! |----------|-------------|
291//! | [`oxide_sdk::camera_open`] / [`oxide_sdk::camera_close`] | Camera stream |
292//! | [`oxide_sdk::camera_capture_frame`] / [`oxide_sdk::camera_frame_dimensions`] | Capture RGBA8 frames |
293//! | [`oxide_sdk::microphone_open`] / [`oxide_sdk::microphone_close`] | Microphone stream |
294//! | [`oxide_sdk::microphone_read_samples`] / [`oxide_sdk::microphone_sample_rate`] | Read mono f32 samples |
295//! | [`oxide_sdk::screen_capture`] / [`oxide_sdk::screen_capture_dimensions`] | Screenshot |
296//!
297//! ## Timers
298//!
299//! Timer callbacks fire via the guest-exported `on_timer(callback_id)` function.
300//!
301//! | Function | Description |
302//! |----------|-------------|
303//! | [`oxide_sdk::set_timeout`] | One-shot timer after a delay |
304//! | [`oxide_sdk::set_interval`] | Repeating timer at an interval |
305//! | [`oxide_sdk::clear_timer`] | Cancel a timer |
306//! | [`oxide_sdk::time_now_ms`] | Current time (ms since UNIX epoch) |
307//!
308//! ## Animation Frames
309//!
310//! Vsync-aligned callbacks for smooth rendering. Callbacks fire via the
311//! guest-exported `on_timer(callback_id)` function (the same export used by
312//! [`oxide_sdk::set_timeout`]), one-shot per request.
313//!
314//! | Function | Description |
315//! |----------|-------------|
316//! | [`oxide_sdk::request_animation_frame`] | Schedule a one-shot frame callback |
317//! | [`oxide_sdk::cancel_animation_frame`] | Cancel a pending request |
318//!
319//! ## Streaming HTTP
320//!
321//! Non-blocking variant of [`oxide_sdk::fetch`] that streams the response body
322//! back to the guest in chunks. Returns immediately with a handle; poll
323//! [`oxide_sdk::fetch_state`] and [`oxide_sdk::fetch_recv`] each frame.
324//!
325//! | Function | Description |
326//! |----------|-------------|
327//! | [`oxide_sdk::fetch_begin`] | Dispatch a streaming request, returns a handle |
328//! | [`oxide_sdk::fetch_begin_get`] | GET shorthand |
329//! | [`oxide_sdk::fetch_state`] | Poll lifecycle state (`FETCH_*` constants) |
330//! | [`oxide_sdk::fetch_status`] | HTTP status code, or `0` until headers arrive |
331//! | [`oxide_sdk::fetch_recv`] | Poll the next body chunk as a [`oxide_sdk::FetchChunk`] |
332//! | [`oxide_sdk::fetch_recv_into`] | Poll into a caller-provided buffer (no allocation) |
333//! | [`oxide_sdk::fetch_error`] | Retrieve the error message for a failed request |
334//! | [`oxide_sdk::fetch_abort`] | Cancel an in-flight request |
335//!
336//! ## WebSocket
337//!
338//! Long-lived bidirectional connections. Messages are queued on the host and
339//! drained by the guest each frame via [`oxide_sdk::ws_recv`].
340//!
341//! | Function | Description |
342//! |----------|-------------|
343//! | [`oxide_sdk::ws_connect`] | Open a WebSocket, returns a handle |
344//! | [`oxide_sdk::ws_ready_state`] | Poll state ([`oxide_sdk::WS_OPEN`], etc.) |
345//! | [`oxide_sdk::ws_send_text`] | Send a UTF-8 text frame |
346//! | [`oxide_sdk::ws_send_binary`] | Send a binary frame |
347//! | [`oxide_sdk::ws_recv`] | Pop the next [`oxide_sdk::WsMessage`] from the queue |
348//! | [`oxide_sdk::ws_close`] | Initiate the close handshake |
349//! | [`oxide_sdk::ws_remove`] | Free host resources after close completes |
350//!
351//! ## MIDI Devices
352//!
353//! Read and write MIDI messages on hardware controllers and synthesisers.
354//! Each input port maintains a bounded queue; long SysEx packets are split.
355//!
356//! | Function | Description |
357//! |----------|-------------|
358//! | [`oxide_sdk::midi_input_count`] / [`oxide_sdk::midi_output_count`] | Enumerate ports |
359//! | [`oxide_sdk::midi_input_name`] / [`oxide_sdk::midi_output_name`] | Look up port names |
360//! | [`oxide_sdk::midi_open_input`] / [`oxide_sdk::midi_open_output`] | Open a port, returns a handle |
361//! | [`oxide_sdk::midi_send`] | Send raw MIDI bytes to an output |
362//! | [`oxide_sdk::midi_recv`] | Pop the next packet from an input queue |
363//! | [`oxide_sdk::midi_close`] | Close a port |
364//!
365//! ## GPU
366//!
367//! WebGPU-style API for GPU-backed buffers, textures, shaders, and
368//! pipelines. Shader source is WGSL.
369//!
370//! | Function | Description |
371//! |----------|-------------|
372//! | [`oxide_sdk::gpu_create_buffer`] | Allocate a GPU buffer |
373//! | [`oxide_sdk::gpu_create_texture`] | Allocate a 2D texture |
374//! | [`oxide_sdk::gpu_create_shader`] | Compile a WGSL shader module |
375//! | [`oxide_sdk::gpu_create_pipeline`] | Build a render pipeline |
376//! | [`oxide_sdk::gpu_create_compute_pipeline`] | Build a compute pipeline |
377//! | [`oxide_sdk::gpu_write_buffer`] | Upload bytes into a buffer |
378//! | [`oxide_sdk::gpu_draw`] | Issue a draw call into a target texture |
379//! | [`oxide_sdk::gpu_dispatch_compute`] | Dispatch a compute workgroup grid |
380//! | [`oxide_sdk::gpu_destroy_buffer`] / [`oxide_sdk::gpu_destroy_texture`] | Release GPU resources |
381//!
382//! ## Navigation & History
383//!
384//! | Function | Description |
385//! |----------|-------------|
386//! | [`oxide_sdk::navigate`] | Navigate to a new URL |
387//! | [`oxide_sdk::push_state`] | Push history entry (like `pushState()`) |
388//! | [`oxide_sdk::replace_state`] | Replace current history entry |
389//! | [`oxide_sdk::get_url`] | Get current page URL |
390//! | [`oxide_sdk::history_back`] / [`oxide_sdk::history_forward`] | Navigate history |
391//!
392//! ## Input Polling
393//!
394//! | Function | Description |
395//! |----------|-------------|
396//! | [`oxide_sdk::mouse_position`] | Mouse `(x, y)` in canvas coordinates |
397//! | [`oxide_sdk::mouse_button_down`] / [`oxide_sdk::mouse_button_clicked`] | Mouse button state |
398//! | [`oxide_sdk::key_down`] / [`oxide_sdk::key_pressed`] | Keyboard state |
399//! | [`oxide_sdk::scroll_delta`] | Scroll wheel delta |
400//! | [`oxide_sdk::shift_held`] / [`oxide_sdk::ctrl_held`] / [`oxide_sdk::alt_held`] | Modifier keys |
401//!
402//! ## Interactive Widgets
403//!
404//! Widgets are rendered during the `on_frame()` loop:
405//!
406//! | Function | Description |
407//! |----------|-------------|
408//! | [`oxide_sdk::ui_button`] | Clickable button, returns `true` when clicked |
409//! | [`oxide_sdk::ui_checkbox`] | Checkbox, returns current checked state |
410//! | [`oxide_sdk::ui_slider`] | Slider, returns current value |
411//! | [`oxide_sdk::ui_text_input`] | Text input field, returns current text |
412//!
413//! ## Crypto & Encoding
414//!
415//! | Function | Description |
416//! |----------|-------------|
417//! | [`oxide_sdk::hash_sha256`] | SHA-256 hash (32-byte array) |
418//! | [`oxide_sdk::hash_sha256_hex`] | SHA-256 hash (hex string) |
419//! | [`oxide_sdk::base64_encode`] / [`oxide_sdk::base64_decode`] | Base64 encoding/decoding |
420//!
421//! ## Other APIs
422//!
423//! | Function | Description |
424//! |----------|-------------|
425//! | [`oxide_sdk::clipboard_write`] / [`oxide_sdk::clipboard_read`] | System clipboard access |
426//! | [`oxide_sdk::random_u64`] / [`oxide_sdk::random_f64`] | Cryptographic random numbers |
427//! | [`oxide_sdk::notify`] | Send a notification |
428//! | [`oxide_sdk::upload_file`] | Open native file picker |
429//! | [`oxide_sdk::get_location`] | Mock geolocation |
430//! | [`oxide_sdk::load_module`] | Dynamically load another `.wasm` module |
431//! | [`oxide_sdk::register_hyperlink`] / [`oxide_sdk::clear_hyperlinks`] | Canvas hyperlinks |
432//! | [`oxide_sdk::url_resolve`] / [`oxide_sdk::url_encode`] / [`oxide_sdk::url_decode`] | URL utilities |
433//!
434//! ---
435//!
436//! # Browser Internals
437//!
438//! The [`oxide_browser`] crate contains the host-side implementation.
439//! Key modules for contributors:
440//!
441//! - **[`oxide_browser::engine`]** — Wasmtime engine setup, [`oxide_browser::engine::SandboxPolicy`],
442//!   fuel metering, bounded linear memory
443//! - **[`oxide_browser::runtime`]** — [`oxide_browser::runtime::BrowserHost`] orchestrates module
444//!   fetching, compilation, and execution. [`oxide_browser::runtime::LiveModule`] keeps interactive
445//!   apps alive across frames.
446//! - **[`oxide_browser::capabilities`]** — The `"oxide"` import module: every host function the
447//!   guest can call is registered here via `register_host_functions()`. Also contains shared state
448//!   types ([`oxide_browser::capabilities::HostState`], [`oxide_browser::capabilities::CanvasState`],
449//!   [`oxide_browser::capabilities::InputState`], etc.).
450//! - **[`oxide_browser::navigation`]** — [`oxide_browser::navigation::NavigationStack`] implements
451//!   browser-style back/forward history with opaque state.
452//! - **[`oxide_browser::bookmarks`]** — [`oxide_browser::bookmarks::BookmarkStore`] provides
453//!   persistent bookmark storage backed by sled.
454//! - **[`oxide_browser::url`]** — [`oxide_browser::url::OxideUrl`] wraps WHATWG URL parsing with
455//!   support for `http`, `https`, `file`, and `oxide://` schemes.
456//! - **[`oxide_browser::ui`]** — [`oxide_browser::ui::OxideBrowserView`] and [`oxide_browser::ui::run_browser`]
457//!   implement tabbed browsing, toolbar, canvas rendering, console panel, and bookmarks sidebar.
458//! - **[`oxide_browser::video`]**, **[`oxide_browser::audio_format`]**, **[`oxide_browser::media_capture`]** —
459//!   FFmpeg video pipeline, audio format sniffing, and camera/microphone/screen capture host state.
460//! - **[`oxide_browser::gpu`]** — WebGPU-style host state: buffers, textures, shaders, and render/compute pipelines.
461//! - **[`oxide_browser::rtc`]** — WebRTC peer connections, data channels, media tracks, and the built-in signalling client.
462//! - **[`oxide_browser::websocket`]** — WebSocket host state: connection registry, send/recv queues, and ready-state tracking.
463//! - **[`oxide_browser::midi`]** — MIDI input/output port enumeration, bounded receive queues, and packet splitting.
464//! - **[`oxide_browser::fetch`]** — Streaming fetch host state: in-flight handles, body chunk queue, and abort tracking.
465//! - **[`oxide_browser::download`]** — Background downloader for non-WASM URLs surfaced as files in the host UI.
466//!
467//! ---
468//!
469//! # Guest Module Contract
470//!
471//! Every `.wasm` module loaded by Oxide must:
472//!
473//! 1. **Export `start_app`** — `extern "C" fn()` entry point called on load
474//! 2. **Optionally export `on_frame`** — `extern "C" fn(dt_ms: u32)` for
475//!    interactive apps with a render loop
476//! 3. **Optionally export `on_timer`** — `extern "C" fn(callback_id: u32)`
477//!    to receive timer callbacks
478//! 4. **Import from `"oxide"`** — all host APIs live under this namespace
479//! 5. **Compile as `cdylib`** — `crate-type = ["cdylib"]` in `Cargo.toml`
480//! 6. **Target `wasm32-unknown-unknown`** — no WASI, pure capability-based
481//!
482//! ---
483//!
484//! # Security Model
485//!
486//! | Constraint | Value | Purpose |
487//! |-----------|-------|---------|
488//! | Filesystem access | None | Guest cannot read/write host files |
489//! | Environment variables | None | Guest cannot inspect host env |
490//! | Raw network sockets | None | All networking is mediated via `fetch` |
491//! | Memory limit | 256 MB (4096 pages) | Prevents memory exhaustion |
492//! | Fuel limit | 500M instructions | Prevents infinite loops / DoS |
493//! | No WASI | — | Zero implicit system access |
494
495pub use oxide_browser;
496pub use oxide_sdk;