Expand description
§EaseRX
EaseRx is a reactive Model-View-Intent (MVI) framework for Rust, designed to reduce the mental overhead of asynchronous programming while providing an intuitive state management solution.
§Overview
Rust’s learning curve can be steep, especially when dealing with asynchronous programming and state management. EaseRx aims to simplify this by providing a structured architecture that allows developers to write asynchronous code in a synchronous style, with automatic error conversion.
§Core Features
- Reactive State Management: Complete solution for managing application state with automatic propagation of state changes
- Simplified Async Programming: Write asynchronous code in a synchronous style
- Automatic Error Conversion: Unified error handling mechanism that automatically converts various error types
- Cancellable Operations: Support for cancellation of long-running operations
- Timeout Handling: Built-in support for operation timeouts
- Retained Values: Keep previous values while loading new data
§Key Components
§StateStore
StateStore
is the core component of EaseRx, responsible for managing application state and providing
a reactive interface for state changes. It supports various execution modes including synchronous,
asynchronous, cancellable, and operations with timeout.
use futures_signals::signal::SignalExt;
use easerx::{StateStore, State, Async};
#[derive(Clone, Debug, PartialEq)]
struct AppState { num: i32, data: Async<String> }
impl State for AppState {}
impl AppState{
fn set_num(self, num: i32) -> Self {
Self { num, ..self }
}
fn set_data(self, data: Async<String>) -> Self {
Self { data , ..self}
}
}
#[tokio::main]
async fn main()-> Result<(), Box<dyn std::error::Error>> {
let store = StateStore::new(AppState { num: 0, data: Async::Uninitialized });
// Update state
store.set_state(|state| {
state.set_num(1)
})?;
// Execute an operation that updates state
store.execute(
|| "example computation".to_string(),
|state, result| {
state.set_data(result)
}
);
store.to_signal()
.stop_if(|state| {state.data.is_complete()})
.for_each(|state| {
println!("state: {:?}", state);
async {}
}).await;
Ok(())
}
§Async State Representation
Async<T>
encapsulates the different states of an asynchronous operation:
Uninitialized
: Initial state before any operation has been attemptedLoading
: Operation in progress (optionally retaining previous value)Success
: Operation completed successfully with a result valueFail
: Operation failed with an error (optionally retaining previous value)
match state_data {
Async::Uninitialized => println!("Not started"),
Async::Loading { .. } => println!("Loading..."),
Async::Success { value } => println!("Data: {}", value),
Async::Fail { error, .. } => println!("Error: {}", error),
}
§Execution Result Conversion
The ExecutionResult
trait provides a unified way to convert different result types
(direct values, Result<T, E>
, and Option<T>
) into the Async<T>
type. This simplifies
error handling by automatically converting various error types into the appropriate Async
variant.
§Stream Extensions
The EaseRxStreamExt
trait extends the functionality of Stream
types with additional
utility methods like stop_if
, which creates a stream that stops producing items once a
predicate returns true.
§Execution Methods
StateStore
provides various execution methods to suit different scenarios:
-
Synchronous Operations:
execute
: Basic synchronous operationexecute_with_retain
: Retain previous values during loadingexecute_cancellable
: Support for cancellationexecute_with_timeout
: Automatic timeout handling
-
Asynchronous Operations:
async_execute
: Basic asynchronous operationasync_execute_with_retain
: Retain previous values during loadingasync_execute_cancellable
: Support for cancellationasync_execute_with_timeout
: Automatic timeout handling
§Design Principles
- Simplicity: API design is clear and easy to understand and use
- Consistency: Maintains consistent interfaces and behavior patterns
- Composability: Components can be flexibly combined to meet different needs
- Type Safety: Leverages Rust’s type system to ensure code safety
- Performance: Prioritizes performance in design decisions
Modules§
Macros§
Structs§
- State
Store - A reactive state container that manages state updates and provides mechanisms for both synchronous and asynchronous operations.
- StopIf
- A stream that stops producing items once a predicate returns true.
Enums§
- Async
- Represents the state of an asynchronous operation with its possible outcomes.
- Async
Error - Represents errors that can occur during asynchronous operations.
Traits§
- Ease
RxStream Ext - Extension trait that provides additional utility methods for Stream types.
- Execution
Result - A trait for converting various result types into the
Async<T>
representation. - State
- A trait for types that can be used as state in a
StateStore
.