use nexus_rt::{Handler, IntoHandler, Local, Param, Res, ResMut, Resource, WorldBuilder};
#[derive(Resource, Default)]
struct OrderBook {
best_bid: f64,
best_ask: f64,
}
#[derive(Resource, Default)]
struct RiskState {
exposure: f64,
}
#[derive(Resource, Default)]
struct Config {
max_exposure: f64,
}
#[derive(Param)]
struct BasicParams<'w> {
book: Res<'w, OrderBook>,
risk: ResMut<'w, RiskState>,
}
fn handler_basic(mut params: BasicParams<'_>, _event: u32) {
let spread = params.book.best_ask - params.book.best_bid;
params.risk.exposure += spread;
}
#[test]
fn basic_res_resmut() {
let mut wb = WorldBuilder::new();
wb.register(OrderBook {
best_bid: 100.0,
best_ask: 101.0,
});
wb.register(RiskState::default());
let mut world = wb.build();
let mut h = handler_basic.into_handler(world.registry());
h.run(&mut world, 0u32);
assert_eq!(world.resource::<RiskState>().exposure, 1.0);
}
#[derive(Param)]
struct ParamsWithLocal<'w> {
config: Res<'w, Config>,
call_count: Local<'w, u64>,
}
fn handler_with_local(mut params: ParamsWithLocal<'_>, _event: ()) {
*params.call_count += 1;
let _ = params.config.max_exposure;
}
#[test]
fn with_local() {
let mut wb = WorldBuilder::new();
wb.register(Config {
max_exposure: 1000.0,
});
let mut world = wb.build();
let mut h = handler_with_local.into_handler(world.registry());
h.run(&mut world, ());
h.run(&mut world, ());
h.run(&mut world, ());
}
#[derive(Param)]
struct OptionalParams<'w> {
config: Option<Res<'w, Config>>,
risk: ResMut<'w, RiskState>,
}
fn handler_optional(mut params: OptionalParams<'_>, _event: ()) {
if let Some(config) = params.config {
params.risk.exposure = config.max_exposure;
}
}
#[test]
fn with_optional_res() {
let mut wb = WorldBuilder::new();
wb.register(RiskState::default());
let mut world = wb.build();
let mut h = handler_optional.into_handler(world.registry());
h.run(&mut world, ());
assert_eq!(world.resource::<RiskState>().exposure, 0.0);
let mut wb2 = WorldBuilder::new();
wb2.register(RiskState::default());
wb2.register(Config {
max_exposure: 500.0,
});
let mut world2 = wb2.build();
let mut h2 = handler_optional.into_handler(world2.registry());
h2.run(&mut world2, ());
assert_eq!(world2.resource::<RiskState>().exposure, 500.0);
}
#[derive(Param)]
struct ParamsWithIgnored<'w> {
risk: ResMut<'w, RiskState>,
#[param(ignore)]
_marker: std::marker::PhantomData<u32>,
}
fn handler_ignored(mut params: ParamsWithIgnored<'_>, _event: ()) {
params.risk.exposure += 1.0;
}
#[test]
fn with_ignored_field() {
let mut wb = WorldBuilder::new();
wb.register(RiskState::default());
let mut world = wb.build();
let mut h = handler_ignored.into_handler(world.registry());
h.run(&mut world, ());
assert_eq!(world.resource::<RiskState>().exposure, 1.0);
}
#[derive(Param)]
struct InnerParams<'w> {
risk: ResMut<'w, RiskState>,
}
#[derive(Param)]
struct OuterParams<'w> {
inner: InnerParams<'w>,
config: Res<'w, Config>,
}
fn handler_nested(mut params: OuterParams<'_>, _event: ()) {
params.inner.risk.exposure = params.config.max_exposure;
}
#[test]
fn nested_params() {
let mut wb = WorldBuilder::new();
wb.register(RiskState::default());
wb.register(Config {
max_exposure: 999.0,
});
let mut world = wb.build();
let mut h = handler_nested.into_handler(world.registry());
h.run(&mut world, ());
assert_eq!(world.resource::<RiskState>().exposure, 999.0);
}
#[derive(Param)]
struct TradingParams<'w> {
book: Res<'w, OrderBook>,
risk: ResMut<'w, RiskState>,
}
fn handler_mixed(mut params: TradingParams<'_>, config: Res<Config>, _event: ()) {
params.risk.exposure = params.book.best_bid * config.max_exposure;
}
#[test]
fn param_plus_additional_resources() {
let mut wb = WorldBuilder::new();
wb.register(OrderBook {
best_bid: 50.0,
best_ask: 51.0,
});
wb.register(RiskState::default());
wb.register(Config { max_exposure: 2.0 });
let mut world = wb.build();
let mut h = handler_mixed.into_handler(world.registry());
h.run(&mut world, ());
assert_eq!(world.resource::<RiskState>().exposure, 100.0);
}