pub struct WorldBuilder { /* private fields */ }Expand description
Builder for registering resources before freezing into a World container.
Each resource type can only be registered once. Registration assigns a
dense ResourceId index (0, 1, 2, …).
The registry() method exposes the type-to-index mapping
so that drivers can resolve systems against the builder before build().
§Examples
use nexus_rt::WorldBuilder;
let mut builder = WorldBuilder::new();
builder.register::<u64>(42);
builder.register::<bool>(true);
let world = builder.build();
let id = world.id::<u64>();
unsafe {
assert_eq!(*world.get::<u64>(id), 42);
}Implementations§
Source§impl WorldBuilder
impl WorldBuilder
Sourcepub fn new() -> Self
pub fn new() -> Self
Create an empty builder.
Examples found in repository?
70fn main() {
71 println!("=== Scenario 1: All optional resources present ===\n");
72 {
73 let mut builder = WorldBuilder::new();
74 builder
75 .register(Config { threshold: 5.0 })
76 .register(DebugLog {
77 entries: Vec::new(),
78 })
79 .register(Metrics {
80 events_processed: 0,
81 });
82 let mut world = builder.build();
83
84 let mut process = process_event.into_handler(world.registry_mut());
85 let mut track = track_metrics.into_handler(world.registry_mut());
86
87 for value in [3.0, 7.5, 1.2] {
88 process.run(&mut world, value);
89 track.run(&mut world, value);
90 println!();
91 }
92
93 let log = world.resource::<DebugLog>();
94 println!("Debug log entries: {:?}", log.entries);
95
96 let metrics = world.resource::<Metrics>();
97 println!("Events processed: {}", metrics.events_processed);
98 }
99
100 println!("\n=== Scenario 2: No optional resources ===\n");
101 {
102 let mut builder = WorldBuilder::new();
103 builder.register(Config { threshold: 5.0 });
104 // DebugLog and Metrics intentionally not registered.
105 let mut world = builder.build();
106
107 let mut process = process_event.into_handler(world.registry_mut());
108 let mut track = track_metrics.into_handler(world.registry_mut());
109
110 for value in [3.0, 7.5] {
111 process.run(&mut world, value);
112 track.run(&mut world, value);
113 println!();
114 }
115
116 println!("Handlers ran cleanly without optional resources.");
117 }
118
119 println!("\nDone.");
120}More examples
51fn main() {
52 println!("=== Example 1: Simple counter ===\n");
53 {
54 let mut world = WorldBuilder::new().build();
55 let mut sys = counting_handler.into_handler(world.registry_mut());
56
57 sys.run(&mut world, "alpha");
58 sys.run(&mut world, "beta");
59 sys.run(&mut world, "gamma");
60 }
61
62 println!("\n=== Example 2: Independent instances ===\n");
63 {
64 let mut builder = WorldBuilder::new();
65 builder.register::<i64>(0);
66 let mut world = builder.build();
67
68 // Two handlers from the same function — each has its own Local<i64>.
69 let mut sys_a = accumulator.into_handler(world.registry_mut());
70 let mut sys_b = accumulator.into_handler(world.registry_mut());
71
72 println!("sys_a gets 10:");
73 sys_a.run(&mut world, 10i64);
74
75 println!("sys_b gets 20:");
76 sys_b.run(&mut world, 20i64);
77
78 println!("sys_a gets 5:");
79 sys_a.run(&mut world, 5i64);
80
81 // sys_a local: 15, sys_b local: 20, world total: 35
82 println!("\nWorld total: {}", world.resource::<i64>());
83 assert_eq!(*world.resource::<i64>(), 35);
84 }
85
86 println!("\n=== Example 3: Batch buffer ===\n");
87 {
88 let mut builder = WorldBuilder::new();
89 builder.register::<Vec<u32>>(Vec::new());
90 let mut world = builder.build();
91
92 let mut sys = batch_writer.into_handler(world.registry_mut());
93
94 // First two events accumulate locally.
95 sys.run(&mut world, 1u32);
96 println!(" output len: {}", world.resource::<Vec<u32>>().len());
97
98 sys.run(&mut world, 2u32);
99 println!(" output len: {}", world.resource::<Vec<u32>>().len());
100
101 // Third event triggers flush.
102 sys.run(&mut world, 3u32);
103 println!(" output len: {}", world.resource::<Vec<u32>>().len());
104
105 // Fourth event starts a new batch.
106 sys.run(&mut world, 4u32);
107 println!(" output len: {}", world.resource::<Vec<u32>>().len());
108
109 let output = world.resource::<Vec<u32>>();
110 println!("\nFinal output: {:?}", &*output);
111 assert_eq!(&*output, &[1, 2, 3]);
112 }
113
114 println!("\nDone.");
115}80fn main() {
81 // --- Bare value pipeline: arity-0 closure stages ---
82
83 println!("=== Bare Value Pipeline ===\n");
84
85 let mut world = WorldBuilder::new().build();
86 let r = world.registry_mut();
87
88 let mut bare_pipeline = PipelineStart::<u32>::new()
89 .stage(|x: u32| x * 2, r)
90 .stage(|x: u32| x + 1, r);
91
92 println!(" 5 → {}", bare_pipeline.run(&mut world, 5));
93 println!(" 10 → {}", bare_pipeline.run(&mut world, 10));
94
95 // --- Option pipeline: filter + inspect (cold path), map (hot path) ---
96
97 println!("\n=== Option Pipeline ===\n");
98
99 let mut wb = WorldBuilder::new();
100 wb.register(PriceCache::new());
101 let mut world = wb.build();
102 let r = world.registry_mut();
103
104 let mut option_pipeline = PipelineStart::<MarketTick>::new()
105 .stage(
106 |tick: MarketTick| -> Option<MarketTick> {
107 if tick.price > 0.0 { Some(tick) } else { None }
108 },
109 r,
110 )
111 .filter(|_w, tick| tick.symbol == "BTC")
112 .inspect(|_w, tick| {
113 println!(" [inspect] {} @ {:.2}", tick.symbol, tick.price);
114 })
115 .map(store_price, r);
116
117 let ticks = [
118 MarketTick {
119 symbol: "BTC",
120 price: 50_000.0,
121 },
122 MarketTick {
123 symbol: "ETH",
124 price: 3_000.0,
125 }, // filtered: not BTC
126 MarketTick {
127 symbol: "BTC",
128 price: -1.0,
129 }, // filtered: negative
130 MarketTick {
131 symbol: "BTC",
132 price: 51_000.0,
133 },
134 ];
135
136 for tick in ticks {
137 option_pipeline.run(&mut world, tick);
138 }
139
140 let cache = world.resource::<PriceCache>();
141 println!(
142 "\n PriceCache: latest={:.2}, updates={}",
143 cache.latest, cache.updates
144 );
145 assert_eq!(cache.updates, 2);
146 assert_eq!(cache.latest, 51_000.0);
147
148 // --- Result pipeline: validate → check → catch → store ---
149
150 println!("\n=== Result Pipeline with catch ===\n");
151
152 let mut wb = WorldBuilder::new();
153 wb.register(PriceCache::new());
154 wb.register::<u64>(0); // error counter
155 let mut world = wb.build();
156 let r = world.registry_mut();
157
158 let mut result_pipeline = PipelineStart::<MarketTick>::new()
159 .stage(validate, r)
160 .and_then(check_known, r)
161 .catch(count_error, r)
162 .map(store_price, r);
163
164 let ticks = [
165 MarketTick {
166 symbol: "BTC",
167 price: 52_000.0,
168 },
169 MarketTick {
170 symbol: "XYZ",
171 price: 100.0,
172 }, // unknown symbol → catch
173 MarketTick {
174 symbol: "ETH",
175 price: -5.0,
176 }, // invalid price → catch
177 MarketTick {
178 symbol: "ETH",
179 price: 3_500.0,
180 },
181 ];
182
183 for tick in ticks {
184 result_pipeline.run(&mut world, tick);
185 }
186
187 let errors = *world.resource::<u64>();
188 println!("\n Errors: {errors}");
189 assert_eq!(errors, 2);
190
191 // --- Build into Handler ---
192
193 println!("\n=== Pipeline as Handler ===\n");
194
195 let mut wb = WorldBuilder::new();
196 wb.register::<u64>(0);
197 let mut world = wb.build();
198 let r = world.registry_mut();
199
200 let mut pipeline = PipelineStart::<u32>::new().stage(accumulate, r).build();
201
202 pipeline.run(&mut world, 10);
203 pipeline.run(&mut world, 20);
204 pipeline.run(&mut world, 30);
205
206 let total = *world.resource::<u64>();
207 println!(" Total: {total}");
208 assert_eq!(total, 60);
209
210 println!("\nDone.");
211}Sourcepub fn register<T: Send + 'static>(&mut self, value: T) -> &mut Self
pub fn register<T: Send + 'static>(&mut self, value: T) -> &mut Self
Register a resource.
The value is heap-allocated via Box and ownership is transferred
to the container. The pointer is stable for the lifetime of the
resulting World.
§Panics
Panics if a resource of the same type is already registered.
Examples found in repository?
70fn main() {
71 println!("=== Scenario 1: All optional resources present ===\n");
72 {
73 let mut builder = WorldBuilder::new();
74 builder
75 .register(Config { threshold: 5.0 })
76 .register(DebugLog {
77 entries: Vec::new(),
78 })
79 .register(Metrics {
80 events_processed: 0,
81 });
82 let mut world = builder.build();
83
84 let mut process = process_event.into_handler(world.registry_mut());
85 let mut track = track_metrics.into_handler(world.registry_mut());
86
87 for value in [3.0, 7.5, 1.2] {
88 process.run(&mut world, value);
89 track.run(&mut world, value);
90 println!();
91 }
92
93 let log = world.resource::<DebugLog>();
94 println!("Debug log entries: {:?}", log.entries);
95
96 let metrics = world.resource::<Metrics>();
97 println!("Events processed: {}", metrics.events_processed);
98 }
99
100 println!("\n=== Scenario 2: No optional resources ===\n");
101 {
102 let mut builder = WorldBuilder::new();
103 builder.register(Config { threshold: 5.0 });
104 // DebugLog and Metrics intentionally not registered.
105 let mut world = builder.build();
106
107 let mut process = process_event.into_handler(world.registry_mut());
108 let mut track = track_metrics.into_handler(world.registry_mut());
109
110 for value in [3.0, 7.5] {
111 process.run(&mut world, value);
112 track.run(&mut world, value);
113 println!();
114 }
115
116 println!("Handlers ran cleanly without optional resources.");
117 }
118
119 println!("\nDone.");
120}More examples
51fn main() {
52 println!("=== Example 1: Simple counter ===\n");
53 {
54 let mut world = WorldBuilder::new().build();
55 let mut sys = counting_handler.into_handler(world.registry_mut());
56
57 sys.run(&mut world, "alpha");
58 sys.run(&mut world, "beta");
59 sys.run(&mut world, "gamma");
60 }
61
62 println!("\n=== Example 2: Independent instances ===\n");
63 {
64 let mut builder = WorldBuilder::new();
65 builder.register::<i64>(0);
66 let mut world = builder.build();
67
68 // Two handlers from the same function — each has its own Local<i64>.
69 let mut sys_a = accumulator.into_handler(world.registry_mut());
70 let mut sys_b = accumulator.into_handler(world.registry_mut());
71
72 println!("sys_a gets 10:");
73 sys_a.run(&mut world, 10i64);
74
75 println!("sys_b gets 20:");
76 sys_b.run(&mut world, 20i64);
77
78 println!("sys_a gets 5:");
79 sys_a.run(&mut world, 5i64);
80
81 // sys_a local: 15, sys_b local: 20, world total: 35
82 println!("\nWorld total: {}", world.resource::<i64>());
83 assert_eq!(*world.resource::<i64>(), 35);
84 }
85
86 println!("\n=== Example 3: Batch buffer ===\n");
87 {
88 let mut builder = WorldBuilder::new();
89 builder.register::<Vec<u32>>(Vec::new());
90 let mut world = builder.build();
91
92 let mut sys = batch_writer.into_handler(world.registry_mut());
93
94 // First two events accumulate locally.
95 sys.run(&mut world, 1u32);
96 println!(" output len: {}", world.resource::<Vec<u32>>().len());
97
98 sys.run(&mut world, 2u32);
99 println!(" output len: {}", world.resource::<Vec<u32>>().len());
100
101 // Third event triggers flush.
102 sys.run(&mut world, 3u32);
103 println!(" output len: {}", world.resource::<Vec<u32>>().len());
104
105 // Fourth event starts a new batch.
106 sys.run(&mut world, 4u32);
107 println!(" output len: {}", world.resource::<Vec<u32>>().len());
108
109 let output = world.resource::<Vec<u32>>();
110 println!("\nFinal output: {:?}", &*output);
111 assert_eq!(&*output, &[1, 2, 3]);
112 }
113
114 println!("\nDone.");
115}80fn main() {
81 // --- Bare value pipeline: arity-0 closure stages ---
82
83 println!("=== Bare Value Pipeline ===\n");
84
85 let mut world = WorldBuilder::new().build();
86 let r = world.registry_mut();
87
88 let mut bare_pipeline = PipelineStart::<u32>::new()
89 .stage(|x: u32| x * 2, r)
90 .stage(|x: u32| x + 1, r);
91
92 println!(" 5 → {}", bare_pipeline.run(&mut world, 5));
93 println!(" 10 → {}", bare_pipeline.run(&mut world, 10));
94
95 // --- Option pipeline: filter + inspect (cold path), map (hot path) ---
96
97 println!("\n=== Option Pipeline ===\n");
98
99 let mut wb = WorldBuilder::new();
100 wb.register(PriceCache::new());
101 let mut world = wb.build();
102 let r = world.registry_mut();
103
104 let mut option_pipeline = PipelineStart::<MarketTick>::new()
105 .stage(
106 |tick: MarketTick| -> Option<MarketTick> {
107 if tick.price > 0.0 { Some(tick) } else { None }
108 },
109 r,
110 )
111 .filter(|_w, tick| tick.symbol == "BTC")
112 .inspect(|_w, tick| {
113 println!(" [inspect] {} @ {:.2}", tick.symbol, tick.price);
114 })
115 .map(store_price, r);
116
117 let ticks = [
118 MarketTick {
119 symbol: "BTC",
120 price: 50_000.0,
121 },
122 MarketTick {
123 symbol: "ETH",
124 price: 3_000.0,
125 }, // filtered: not BTC
126 MarketTick {
127 symbol: "BTC",
128 price: -1.0,
129 }, // filtered: negative
130 MarketTick {
131 symbol: "BTC",
132 price: 51_000.0,
133 },
134 ];
135
136 for tick in ticks {
137 option_pipeline.run(&mut world, tick);
138 }
139
140 let cache = world.resource::<PriceCache>();
141 println!(
142 "\n PriceCache: latest={:.2}, updates={}",
143 cache.latest, cache.updates
144 );
145 assert_eq!(cache.updates, 2);
146 assert_eq!(cache.latest, 51_000.0);
147
148 // --- Result pipeline: validate → check → catch → store ---
149
150 println!("\n=== Result Pipeline with catch ===\n");
151
152 let mut wb = WorldBuilder::new();
153 wb.register(PriceCache::new());
154 wb.register::<u64>(0); // error counter
155 let mut world = wb.build();
156 let r = world.registry_mut();
157
158 let mut result_pipeline = PipelineStart::<MarketTick>::new()
159 .stage(validate, r)
160 .and_then(check_known, r)
161 .catch(count_error, r)
162 .map(store_price, r);
163
164 let ticks = [
165 MarketTick {
166 symbol: "BTC",
167 price: 52_000.0,
168 },
169 MarketTick {
170 symbol: "XYZ",
171 price: 100.0,
172 }, // unknown symbol → catch
173 MarketTick {
174 symbol: "ETH",
175 price: -5.0,
176 }, // invalid price → catch
177 MarketTick {
178 symbol: "ETH",
179 price: 3_500.0,
180 },
181 ];
182
183 for tick in ticks {
184 result_pipeline.run(&mut world, tick);
185 }
186
187 let errors = *world.resource::<u64>();
188 println!("\n Errors: {errors}");
189 assert_eq!(errors, 2);
190
191 // --- Build into Handler ---
192
193 println!("\n=== Pipeline as Handler ===\n");
194
195 let mut wb = WorldBuilder::new();
196 wb.register::<u64>(0);
197 let mut world = wb.build();
198 let r = world.registry_mut();
199
200 let mut pipeline = PipelineStart::<u32>::new().stage(accumulate, r).build();
201
202 pipeline.run(&mut world, 10);
203 pipeline.run(&mut world, 20);
204 pipeline.run(&mut world, 30);
205
206 let total = *world.resource::<u64>();
207 println!(" Total: {total}");
208 assert_eq!(total, 60);
209
210 println!("\nDone.");
211}Sourcepub fn register_default<T: Default + Send + 'static>(&mut self) -> &mut Self
pub fn register_default<T: Default + Send + 'static>(&mut self) -> &mut Self
Register a resource using its Default value.
Equivalent to self.register::<T>(T::default()).
Sourcepub fn registry(&self) -> &Registry
pub fn registry(&self) -> &Registry
Returns a shared reference to the type registry.
Use this for read-only queries. For construction-time calls
like into_system, use
registry_mut instead.
Sourcepub fn registry_mut(&mut self) -> &mut Registry
pub fn registry_mut(&mut self) -> &mut Registry
Returns a mutable reference to the type registry.
Needed at construction time for
into_system,
into_callback, and
into_stage
which call Registry::check_access.
Sourcepub fn contains<T: 'static>(&self) -> bool
pub fn contains<T: 'static>(&self) -> bool
Returns true if a resource of type T has been registered.
Sourcepub fn install_plugin(&mut self, plugin: impl Plugin) -> &mut Self
pub fn install_plugin(&mut self, plugin: impl Plugin) -> &mut Self
Install a plugin. The plugin is consumed and registers its resources into this builder.
Sourcepub fn install_driver<D: Driver>(&mut self, driver: D) -> D::Handle
pub fn install_driver<D: Driver>(&mut self, driver: D) -> D::Handle
Install a driver. The driver is consumed, registers its resources into this builder, and returns a concrete handle for dispatch-time polling.
Sourcepub fn build(self) -> World
pub fn build(self) -> World
Freeze the builder into an immutable World container.
After this call, no more resources can be registered. All
ResourceId values remain valid for the lifetime of the
returned World.
Examples found in repository?
70fn main() {
71 println!("=== Scenario 1: All optional resources present ===\n");
72 {
73 let mut builder = WorldBuilder::new();
74 builder
75 .register(Config { threshold: 5.0 })
76 .register(DebugLog {
77 entries: Vec::new(),
78 })
79 .register(Metrics {
80 events_processed: 0,
81 });
82 let mut world = builder.build();
83
84 let mut process = process_event.into_handler(world.registry_mut());
85 let mut track = track_metrics.into_handler(world.registry_mut());
86
87 for value in [3.0, 7.5, 1.2] {
88 process.run(&mut world, value);
89 track.run(&mut world, value);
90 println!();
91 }
92
93 let log = world.resource::<DebugLog>();
94 println!("Debug log entries: {:?}", log.entries);
95
96 let metrics = world.resource::<Metrics>();
97 println!("Events processed: {}", metrics.events_processed);
98 }
99
100 println!("\n=== Scenario 2: No optional resources ===\n");
101 {
102 let mut builder = WorldBuilder::new();
103 builder.register(Config { threshold: 5.0 });
104 // DebugLog and Metrics intentionally not registered.
105 let mut world = builder.build();
106
107 let mut process = process_event.into_handler(world.registry_mut());
108 let mut track = track_metrics.into_handler(world.registry_mut());
109
110 for value in [3.0, 7.5] {
111 process.run(&mut world, value);
112 track.run(&mut world, value);
113 println!();
114 }
115
116 println!("Handlers ran cleanly without optional resources.");
117 }
118
119 println!("\nDone.");
120}More examples
51fn main() {
52 println!("=== Example 1: Simple counter ===\n");
53 {
54 let mut world = WorldBuilder::new().build();
55 let mut sys = counting_handler.into_handler(world.registry_mut());
56
57 sys.run(&mut world, "alpha");
58 sys.run(&mut world, "beta");
59 sys.run(&mut world, "gamma");
60 }
61
62 println!("\n=== Example 2: Independent instances ===\n");
63 {
64 let mut builder = WorldBuilder::new();
65 builder.register::<i64>(0);
66 let mut world = builder.build();
67
68 // Two handlers from the same function — each has its own Local<i64>.
69 let mut sys_a = accumulator.into_handler(world.registry_mut());
70 let mut sys_b = accumulator.into_handler(world.registry_mut());
71
72 println!("sys_a gets 10:");
73 sys_a.run(&mut world, 10i64);
74
75 println!("sys_b gets 20:");
76 sys_b.run(&mut world, 20i64);
77
78 println!("sys_a gets 5:");
79 sys_a.run(&mut world, 5i64);
80
81 // sys_a local: 15, sys_b local: 20, world total: 35
82 println!("\nWorld total: {}", world.resource::<i64>());
83 assert_eq!(*world.resource::<i64>(), 35);
84 }
85
86 println!("\n=== Example 3: Batch buffer ===\n");
87 {
88 let mut builder = WorldBuilder::new();
89 builder.register::<Vec<u32>>(Vec::new());
90 let mut world = builder.build();
91
92 let mut sys = batch_writer.into_handler(world.registry_mut());
93
94 // First two events accumulate locally.
95 sys.run(&mut world, 1u32);
96 println!(" output len: {}", world.resource::<Vec<u32>>().len());
97
98 sys.run(&mut world, 2u32);
99 println!(" output len: {}", world.resource::<Vec<u32>>().len());
100
101 // Third event triggers flush.
102 sys.run(&mut world, 3u32);
103 println!(" output len: {}", world.resource::<Vec<u32>>().len());
104
105 // Fourth event starts a new batch.
106 sys.run(&mut world, 4u32);
107 println!(" output len: {}", world.resource::<Vec<u32>>().len());
108
109 let output = world.resource::<Vec<u32>>();
110 println!("\nFinal output: {:?}", &*output);
111 assert_eq!(&*output, &[1, 2, 3]);
112 }
113
114 println!("\nDone.");
115}80fn main() {
81 // --- Bare value pipeline: arity-0 closure stages ---
82
83 println!("=== Bare Value Pipeline ===\n");
84
85 let mut world = WorldBuilder::new().build();
86 let r = world.registry_mut();
87
88 let mut bare_pipeline = PipelineStart::<u32>::new()
89 .stage(|x: u32| x * 2, r)
90 .stage(|x: u32| x + 1, r);
91
92 println!(" 5 → {}", bare_pipeline.run(&mut world, 5));
93 println!(" 10 → {}", bare_pipeline.run(&mut world, 10));
94
95 // --- Option pipeline: filter + inspect (cold path), map (hot path) ---
96
97 println!("\n=== Option Pipeline ===\n");
98
99 let mut wb = WorldBuilder::new();
100 wb.register(PriceCache::new());
101 let mut world = wb.build();
102 let r = world.registry_mut();
103
104 let mut option_pipeline = PipelineStart::<MarketTick>::new()
105 .stage(
106 |tick: MarketTick| -> Option<MarketTick> {
107 if tick.price > 0.0 { Some(tick) } else { None }
108 },
109 r,
110 )
111 .filter(|_w, tick| tick.symbol == "BTC")
112 .inspect(|_w, tick| {
113 println!(" [inspect] {} @ {:.2}", tick.symbol, tick.price);
114 })
115 .map(store_price, r);
116
117 let ticks = [
118 MarketTick {
119 symbol: "BTC",
120 price: 50_000.0,
121 },
122 MarketTick {
123 symbol: "ETH",
124 price: 3_000.0,
125 }, // filtered: not BTC
126 MarketTick {
127 symbol: "BTC",
128 price: -1.0,
129 }, // filtered: negative
130 MarketTick {
131 symbol: "BTC",
132 price: 51_000.0,
133 },
134 ];
135
136 for tick in ticks {
137 option_pipeline.run(&mut world, tick);
138 }
139
140 let cache = world.resource::<PriceCache>();
141 println!(
142 "\n PriceCache: latest={:.2}, updates={}",
143 cache.latest, cache.updates
144 );
145 assert_eq!(cache.updates, 2);
146 assert_eq!(cache.latest, 51_000.0);
147
148 // --- Result pipeline: validate → check → catch → store ---
149
150 println!("\n=== Result Pipeline with catch ===\n");
151
152 let mut wb = WorldBuilder::new();
153 wb.register(PriceCache::new());
154 wb.register::<u64>(0); // error counter
155 let mut world = wb.build();
156 let r = world.registry_mut();
157
158 let mut result_pipeline = PipelineStart::<MarketTick>::new()
159 .stage(validate, r)
160 .and_then(check_known, r)
161 .catch(count_error, r)
162 .map(store_price, r);
163
164 let ticks = [
165 MarketTick {
166 symbol: "BTC",
167 price: 52_000.0,
168 },
169 MarketTick {
170 symbol: "XYZ",
171 price: 100.0,
172 }, // unknown symbol → catch
173 MarketTick {
174 symbol: "ETH",
175 price: -5.0,
176 }, // invalid price → catch
177 MarketTick {
178 symbol: "ETH",
179 price: 3_500.0,
180 },
181 ];
182
183 for tick in ticks {
184 result_pipeline.run(&mut world, tick);
185 }
186
187 let errors = *world.resource::<u64>();
188 println!("\n Errors: {errors}");
189 assert_eq!(errors, 2);
190
191 // --- Build into Handler ---
192
193 println!("\n=== Pipeline as Handler ===\n");
194
195 let mut wb = WorldBuilder::new();
196 wb.register::<u64>(0);
197 let mut world = wb.build();
198 let r = world.registry_mut();
199
200 let mut pipeline = PipelineStart::<u32>::new().stage(accumulate, r).build();
201
202 pipeline.run(&mut world, 10);
203 pipeline.run(&mut world, 20);
204 pipeline.run(&mut world, 30);
205
206 let total = *world.resource::<u64>();
207 println!(" Total: {total}");
208 assert_eq!(total, 60);
209
210 println!("\nDone.");
211}