oxide-mvu
A lightweight Model-View-Update (MVU) runtime framework for Rust with no_std support.
Overview
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 the 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
- 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.1.0"
For no_std environments:
[]
= { = "0.1.0", = ["no_std"] }
Usage
Define your types
use ;
Implement the MvuLogic trait
;
Implement a Renderer
use Renderer;
;
Run the application
use MvuRuntime;
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.1.0", = ["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::boxed(): Returns a boxed renderer while keeping a handle for assertions.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.
See tests/lib_test.rs for complete examples.
License
Licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0)