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//! ## Crate Map
12//!
13//! | Crate | Purpose | Audience |
14//! |-------|---------|----------|
15//! | [`oxide_sdk`] | Guest SDK — safe Rust wrappers for the `"oxide"` host imports | App developers |
16//! | [`oxide_browser`] | Host runtime — Wasmtime engine, sandbox, egui UI | Browser contributors |
17//!
18//! ---
19//!
20//! # Quick Start — Building a Guest App
21//!
22//! ```toml
23//! # Cargo.toml
24//! [package]
25//! name = "my-oxide-app"
26//! version = "0.1.0"
27//! edition = "2021"
28//!
29//! [lib]
30//! crate-type = ["cdylib"]
31//!
32//! [dependencies]
33//! oxide-sdk = "0.2"
34//! ```
35//!
36//! ```rust,ignore
37//! // src/lib.rs
38//! use oxide_sdk::*;
39//!
40//! #[no_mangle]
41//! pub extern "C" fn start_app() {
42//!     log("Hello from Oxide!");
43//!     canvas_clear(30, 30, 46, 255);
44//!     canvas_text(20.0, 40.0, 28.0, 255, 255, 255, "Welcome to Oxide");
45//! }
46//! ```
47//!
48//! Build and run:
49//!
50//! ```bash
51//! cargo build --target wasm32-unknown-unknown --release
52//! # Open Oxide browser → navigate to your .wasm file
53//! ```
54//!
55//! ---
56//!
57//! # Architecture Overview
58//!
59//! ```text
60//! ┌─────────────────────────────────────────────────────┐
61//! │                    Oxide Browser                    │
62//! │                                                     │
63//! │  ┌──────────┐  ┌────────────┐  ┌──────────────────┐ │
64//! │  │  URL Bar │  │   Canvas   │  │     Console      │ │
65//! │  └────┬─────┘  └──────┬─────┘  └──────┬───────────┘ │
66//! │       │               │               │             │
67//! │  ┌────▼───────────────▼───────────────▼──────────┐  │
68//! │  │              Host Runtime (oxide-browser)      │  │
69//! │  │  Wasmtime engine · sandbox policy             │  │
70//! │  │  fuel: 500M instructions · memory: 16 MB      │  │
71//! │  └────────────────────┬──────────────────────────┘  │
72//! │                       │                             │
73//! │  ┌────────────────────▼──────────────────────────┐  │
74//! │  │          Capability Provider                  │  │
75//! │  │  "oxide" wasm import module                   │  │
76//! │  │  canvas · console · storage · clipboard       │  │
77//! │  │  fetch · audio · timers · crypto · navigation │  │
78//! │  │  widgets · input · hyperlinks · protobuf      │  │
79//! │  └────────────────────┬──────────────────────────┘  │
80//! │                       │                             │
81//! │  ┌────────────────────▼──────────────────────────┐  │
82//! │  │           Guest .wasm Module (oxide-sdk)       │  │
83//! │  │  exports: start_app(), on_frame(dt_ms)        │  │
84//! │  │  imports: oxide::*                            │  │
85//! │  └───────────────────────────────────────────────┘  │
86//! └─────────────────────────────────────────────────────┘
87//! ```
88//!
89//! ---
90//!
91//! # Guest SDK API Reference
92//!
93//! The [`oxide_sdk`] crate provides the full guest-side API. All functions
94//! are available via `use oxide_sdk::*;`.
95//!
96//! ## Canvas Drawing
97//!
98//! The canvas is the main rendering surface. Coordinates start at `(0, 0)`
99//! in the top-left corner.
100//!
101//! | Function | Description |
102//! |----------|-------------|
103//! | [`oxide_sdk::canvas_clear`] | Clear canvas with a solid RGBA color |
104//! | [`oxide_sdk::canvas_rect`] | Draw a filled rectangle |
105//! | [`oxide_sdk::canvas_circle`] | Draw a filled circle |
106//! | [`oxide_sdk::canvas_text`] | Draw text at a position |
107//! | [`oxide_sdk::canvas_line`] | Draw a line between two points |
108//! | [`oxide_sdk::canvas_dimensions`] | Get canvas `(width, height)` in pixels |
109//! | [`oxide_sdk::canvas_image`] | Draw an encoded image (PNG, JPEG, GIF, WebP) |
110//!
111//! ```rust,ignore
112//! use oxide_sdk::*;
113//!
114//! canvas_clear(30, 30, 46, 255);
115//! canvas_rect(10.0, 10.0, 200.0, 100.0, 80, 120, 200, 255);
116//! canvas_circle(300.0, 200.0, 50.0, 200, 100, 150, 255);
117//! canvas_text(20.0, 30.0, 24.0, 255, 255, 255, "Hello!");
118//! canvas_line(0.0, 0.0, 400.0, 300.0, 255, 200, 0, 2.0);
119//!
120//! let (w, h) = canvas_dimensions();
121//! log(&format!("Canvas: {}x{}", w, h));
122//! ```
123//!
124//! ## Console Logging
125//!
126//! | Function | Description |
127//! |----------|-------------|
128//! | [`oxide_sdk::log`] | Print an informational message |
129//! | [`oxide_sdk::warn`] | Print a warning (yellow) |
130//! | [`oxide_sdk::error`] | Print an error (red) |
131//!
132//! ## HTTP Networking
133//!
134//! All network access is mediated by the host — the guest never opens raw
135//! sockets. **Protocol Buffers** is the native wire format.
136//!
137//! | Function | Description |
138//! |----------|-------------|
139//! | [`oxide_sdk::fetch`] | Full HTTP request with method, headers, body |
140//! | [`oxide_sdk::fetch_get`] | HTTP GET shorthand |
141//! | [`oxide_sdk::fetch_post`] | HTTP POST with content-type and body |
142//! | [`oxide_sdk::fetch_post_proto`] | HTTP POST with protobuf body |
143//! | [`oxide_sdk::fetch_put`] | HTTP PUT |
144//! | [`oxide_sdk::fetch_delete`] | HTTP DELETE |
145//!
146//! ```rust,ignore
147//! use oxide_sdk::*;
148//!
149//! let resp = fetch_get("https://api.example.com/data").unwrap();
150//! log(&format!("Status: {}, Body: {}", resp.status, resp.text()));
151//! ```
152//!
153//! ## Protobuf — Native Data Format
154//!
155//! The [`oxide_sdk::proto`] module provides a zero-dependency protobuf
156//! encoder/decoder compatible with the Protocol Buffers wire format.
157//!
158//! ```rust,ignore
159//! use oxide_sdk::proto::{ProtoEncoder, ProtoDecoder};
160//!
161//! let msg = ProtoEncoder::new()
162//!     .string(1, "alice")
163//!     .uint64(2, 42)
164//!     .bool(3, true)
165//!     .finish();
166//!
167//! let mut decoder = ProtoDecoder::new(&msg);
168//! while let Some(field) = decoder.next() {
169//!     match field.number {
170//!         1 => log(&format!("name = {}", field.as_str())),
171//!         2 => log(&format!("age  = {}", field.as_u64())),
172//!         _ => {}
173//!     }
174//! }
175//! ```
176//!
177//! ## Storage
178//!
179//! | Function | Description |
180//! |----------|-------------|
181//! | [`oxide_sdk::storage_set`] | Store a key-value pair (session-scoped) |
182//! | [`oxide_sdk::storage_get`] | Retrieve a value by key |
183//! | [`oxide_sdk::storage_remove`] | Delete a key |
184//! | [`oxide_sdk::kv_store_set`] | Persistent on-disk KV store |
185//! | [`oxide_sdk::kv_store_get`] | Read from persistent KV store |
186//! | [`oxide_sdk::kv_store_delete`] | Delete from persistent KV store |
187//!
188//! ## Audio
189//!
190//! | Function | Description |
191//! |----------|-------------|
192//! | [`oxide_sdk::audio_play`] | Play audio from encoded bytes (WAV, MP3, OGG, FLAC) |
193//! | [`oxide_sdk::audio_play_url`] | Fetch audio from a URL and play it |
194//! | [`oxide_sdk::audio_pause`] / [`oxide_sdk::audio_resume`] / [`oxide_sdk::audio_stop`] | Playback control |
195//! | [`oxide_sdk::audio_set_volume`] / [`oxide_sdk::audio_get_volume`] | Volume control (0.0 – 2.0) |
196//! | [`oxide_sdk::audio_is_playing`] | Check playback state |
197//! | [`oxide_sdk::audio_position`] / [`oxide_sdk::audio_seek`] / [`oxide_sdk::audio_duration`] | Seek and position |
198//! | [`oxide_sdk::audio_set_loop`] | Enable/disable looping |
199//! | [`oxide_sdk::audio_channel_play`] | Multi-channel simultaneous playback |
200//!
201//! ## Timers
202//!
203//! Timer callbacks fire via the guest-exported `on_timer(callback_id)` function.
204//!
205//! | Function | Description |
206//! |----------|-------------|
207//! | [`oxide_sdk::set_timeout`] | One-shot timer after a delay |
208//! | [`oxide_sdk::set_interval`] | Repeating timer at an interval |
209//! | [`oxide_sdk::clear_timer`] | Cancel a timer |
210//! | [`oxide_sdk::time_now_ms`] | Current time (ms since UNIX epoch) |
211//!
212//! ## Navigation & History
213//!
214//! | Function | Description |
215//! |----------|-------------|
216//! | [`oxide_sdk::navigate`] | Navigate to a new URL |
217//! | [`oxide_sdk::push_state`] | Push history entry (like `pushState()`) |
218//! | [`oxide_sdk::replace_state`] | Replace current history entry |
219//! | [`oxide_sdk::get_url`] | Get current page URL |
220//! | [`oxide_sdk::history_back`] / [`oxide_sdk::history_forward`] | Navigate history |
221//!
222//! ## Input Polling
223//!
224//! | Function | Description |
225//! |----------|-------------|
226//! | [`oxide_sdk::mouse_position`] | Mouse `(x, y)` in canvas coordinates |
227//! | [`oxide_sdk::mouse_button_down`] / [`oxide_sdk::mouse_button_clicked`] | Mouse button state |
228//! | [`oxide_sdk::key_down`] / [`oxide_sdk::key_pressed`] | Keyboard state |
229//! | [`oxide_sdk::scroll_delta`] | Scroll wheel delta |
230//! | [`oxide_sdk::shift_held`] / [`oxide_sdk::ctrl_held`] / [`oxide_sdk::alt_held`] | Modifier keys |
231//!
232//! ## Interactive Widgets
233//!
234//! Widgets are rendered during the `on_frame()` loop:
235//!
236//! | Function | Description |
237//! |----------|-------------|
238//! | [`oxide_sdk::ui_button`] | Clickable button, returns `true` when clicked |
239//! | [`oxide_sdk::ui_checkbox`] | Checkbox, returns current checked state |
240//! | [`oxide_sdk::ui_slider`] | Slider, returns current value |
241//! | [`oxide_sdk::ui_text_input`] | Text input field, returns current text |
242//!
243//! ## Crypto & Encoding
244//!
245//! | Function | Description |
246//! |----------|-------------|
247//! | [`oxide_sdk::hash_sha256`] | SHA-256 hash (32-byte array) |
248//! | [`oxide_sdk::hash_sha256_hex`] | SHA-256 hash (hex string) |
249//! | [`oxide_sdk::base64_encode`] / [`oxide_sdk::base64_decode`] | Base64 encoding/decoding |
250//!
251//! ## Other APIs
252//!
253//! | Function | Description |
254//! |----------|-------------|
255//! | [`oxide_sdk::clipboard_write`] / [`oxide_sdk::clipboard_read`] | System clipboard access |
256//! | [`oxide_sdk::random_u64`] / [`oxide_sdk::random_f64`] | Cryptographic random numbers |
257//! | [`oxide_sdk::notify`] | Send a notification |
258//! | [`oxide_sdk::upload_file`] | Open native file picker |
259//! | [`oxide_sdk::get_location`] | Mock geolocation |
260//! | [`oxide_sdk::load_module`] | Dynamically load another `.wasm` module |
261//! | [`oxide_sdk::register_hyperlink`] / [`oxide_sdk::clear_hyperlinks`] | Canvas hyperlinks |
262//! | [`oxide_sdk::url_resolve`] / [`oxide_sdk::url_encode`] / [`oxide_sdk::url_decode`] | URL utilities |
263//!
264//! ---
265//!
266//! # Browser Internals
267//!
268//! The [`oxide_browser`] crate contains the host-side implementation.
269//! Key modules for contributors:
270//!
271//! - **[`oxide_browser::engine`]** — Wasmtime engine setup, [`oxide_browser::engine::SandboxPolicy`],
272//!   fuel metering, bounded linear memory
273//! - **[`oxide_browser::runtime`]** — [`oxide_browser::runtime::BrowserHost`] orchestrates module
274//!   fetching, compilation, and execution. [`oxide_browser::runtime::LiveModule`] keeps interactive
275//!   apps alive across frames.
276//! - **[`oxide_browser::capabilities`]** — The `"oxide"` import module: every host function the
277//!   guest can call is registered here via `register_host_functions()`. Also contains shared state
278//!   types ([`oxide_browser::capabilities::HostState`], [`oxide_browser::capabilities::CanvasState`],
279//!   [`oxide_browser::capabilities::InputState`], etc.).
280//! - **[`oxide_browser::navigation`]** — [`oxide_browser::navigation::NavigationStack`] implements
281//!   browser-style back/forward history with opaque state.
282//! - **[`oxide_browser::bookmarks`]** — [`oxide_browser::bookmarks::BookmarkStore`] provides
283//!   persistent bookmark storage backed by sled.
284//! - **[`oxide_browser::url`]** — [`oxide_browser::url::OxideUrl`] wraps WHATWG URL parsing with
285//!   support for `http`, `https`, `file`, and `oxide://` schemes.
286//! - **[`oxide_browser::ui`]** — [`oxide_browser::ui::OxideApp`] is the egui/eframe application
287//!   with tabbed browsing, toolbar, canvas rendering, console panel, and bookmarks sidebar.
288//!
289//! ---
290//!
291//! # Guest Module Contract
292//!
293//! Every `.wasm` module loaded by Oxide must:
294//!
295//! 1. **Export `start_app`** — `extern "C" fn()` entry point called on load
296//! 2. **Optionally export `on_frame`** — `extern "C" fn(dt_ms: u32)` for
297//!    interactive apps with a render loop
298//! 3. **Optionally export `on_timer`** — `extern "C" fn(callback_id: u32)`
299//!    to receive timer callbacks
300//! 4. **Import from `"oxide"`** — all host APIs live under this namespace
301//! 5. **Compile as `cdylib`** — `crate-type = ["cdylib"]` in `Cargo.toml`
302//! 6. **Target `wasm32-unknown-unknown`** — no WASI, pure capability-based
303//!
304//! ---
305//!
306//! # Security Model
307//!
308//! | Constraint | Value | Purpose |
309//! |-----------|-------|---------|
310//! | Filesystem access | None | Guest cannot read/write host files |
311//! | Environment variables | None | Guest cannot inspect host env |
312//! | Raw network sockets | None | All networking is mediated via `fetch` |
313//! | Memory limit | 16 MB (256 pages) | Prevents memory exhaustion |
314//! | Fuel limit | 500M instructions | Prevents infinite loops / DoS |
315//! | No WASI | — | Zero implicit system access |
316
317pub use oxide_browser;
318pub use oxide_sdk;