oxide-mvu
A lightweight Model-View-Update (MVU) runtime framework for Rust with no_std support.
Documentation | Crates.io | Repository | Examples
Overview
(Note that this framework is not yet ready for production, and APIs should not be considered stable)
oxide-mvu implements the MVU pattern for building predictable, testable applications in Rust. The framework is powerful enough
to be a good choice for most applications, but will always evolve with support for no_std, low-memory, single-cpu, embedded systems as a baseline.
Oxide is intended to clarify the management of state in an application using clear separation of concerns between cleanly isolated view and application logic layers.
Features
- Unidirectional data flow: State transitions occur in a single loop:
- → event emission is triggered from an effect or user input
- → update function receives event data and yields new state
- → view function reduces state to renderable props
- → renderer function receives props for display
- Async/await support: Non-blocking event loop using async channels
- Lock-free concurrency: Events can be emitted from any thread without mutex overhead
- Type-safe event dispatch: Callbacks in Props maintain type safety
- Effect system: Controlled, declarative side effects
- no_std support: Works in embedded environments (requires
allocfor heap allocation)
Installation
Add to your Cargo.toml:
[]
= "0.3.1"
For no_std environments:
[]
= { = "0.3.1", = ["no_std"] }
Usage
Define your types
use ;
Implement the MvuLogic trait
;
Implement a Renderer
use Renderer;
;
Create a Spawner
The runtime needs a spawner to execute async effects. The spawner is framework-agnostic,
allowing you to use any async runtime (tokio, async-std, smol, etc.). Any function or
closure that implements the Spawner trait will work:
Using tokio:
let spawner = ;
Using async-std:
let spawner = ;
Run the application
The runtime uses async/await for non-blocking event processing. You can either await the runtime directly or spawn it:
use MvuRuntime;
async
Testing
oxide-mvu provides specialized testing utilities for integration testing your MVU applications.
Enabling Testing Utilities
To access the testing helpers in your project, enable the testing feature:
[]
= { = "0.3.1", = ["testing"] }
This gives you access to:
TestMvuRuntime- Runtime with manual event processing controlTestMvuDriver- Driver for manually processing events in testsTestRenderer- Renderer that captures Props for assertions
Unit Testing
State transitions are pure functions, making them easy to unit test:
Integration Testing
Use TestMvuRuntime and TestRenderer to test the full MVU loop:
use ;
Key Testing Concepts
TestMvuRuntime: UnlikeMvuRuntime, events are not automatically processed. You must calldriver.process_events()to manually drive the event loop.TestRenderer: Captures all rendered Props, allowing you to verify the runtime's output and trigger callbacks.renderer.with_renders(): Access all captured Props for assertions or to trigger callbacks.driver.process_events(): Process all queued events until the queue is empty.create_test_spawner(): Creates a spawner that executes effects synchronously for deterministic testing.
See the tests directory for complete examples.
License
Licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0)