pub struct World { /* private fields */ }Expand description
Frozen singleton resource storage.
Created by WorldBuilder::build(). Resources are indexed by dense
ResourceId for O(1) dispatch-time access (~3 cycles per fetch).
§Safe API
resource/resource_mut— cold-path access via HashMap lookup.
§Unsafe API (framework internals)
The low-level get / get_mut methods are unsafe — used by
SystemParam::fetch for ~3-cycle dispatch.
The caller must ensure no mutable aliasing.
Implementations§
Source§impl World
impl World
Sourcepub fn builder() -> WorldBuilder
pub fn builder() -> WorldBuilder
Convenience constructor — returns a new WorldBuilder.
Sourcepub fn registry(&self) -> &Registry
pub fn registry(&self) -> &Registry
Returns a shared reference to the type registry.
Use this for read-only queries (e.g. id,
contains). 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.
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 id<T: 'static>(&self) -> ResourceId
pub fn id<T: 'static>(&self) -> ResourceId
Resolve the ResourceId for a type. Cold path — uses HashMap lookup.
§Panics
Panics if the resource type was not registered.
Sourcepub fn try_id<T: 'static>(&self) -> Option<ResourceId>
pub fn try_id<T: 'static>(&self) -> Option<ResourceId>
Try to resolve the ResourceId for a type. Returns None if the
type was not registered.
Sourcepub fn resource<T: 'static>(&self) -> &T
pub fn resource<T: 'static>(&self) -> &T
Safe shared access to a resource. Cold path — resolves via HashMap.
Takes &self — multiple shared references can coexist. The borrow
checker prevents mixing with resource_mut
(which takes &mut self).
§Panics
Panics if the resource type was not 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 resource_mut<T: 'static>(&mut self) -> &mut T
pub fn resource_mut<T: 'static>(&mut self) -> &mut T
Safe exclusive access to a resource. Cold path — resolves via HashMap.
§Panics
Panics if the resource type was not registered.
Sourcepub fn current_sequence(&self) -> Sequence
pub fn current_sequence(&self) -> Sequence
Returns the current event sequence number.
Sourcepub fn next_sequence(&mut self) -> Sequence
pub fn next_sequence(&mut self) -> Sequence
Advance to the next event sequence number and return it.
Drivers call this before dispatching each event. The returned
sequence number identifies the event being processed. Resources
mutated during dispatch will record this sequence in changed_at.
Sourcepub unsafe fn get<T: 'static>(&self, id: ResourceId) -> &T
pub unsafe fn get<T: 'static>(&self, id: ResourceId) -> &T
Fetch a shared reference to a resource by pre-validated index.
§Safety
idmust have been returned byWorldBuilder::registerfor the same builder that produced this container.Tmust be the same type that was registered at thisid.- The caller must ensure no mutable reference to this resource exists.
Sourcepub unsafe fn get_mut<T: 'static>(&self, id: ResourceId) -> &mut T
pub unsafe fn get_mut<T: 'static>(&self, id: ResourceId) -> &mut T
Fetch a mutable reference to a resource by pre-validated index.
Takes &self — the container structure is frozen, but individual
resources have interior mutability via raw pointers. Sound because
callers (single-threaded sequential dispatch) uphold no-aliasing.
§Safety
idmust have been returned byWorldBuilder::registerfor the same builder that produced this container.Tmust be the same type that was registered at thisid.- The caller must ensure no other reference (shared or mutable) to this resource exists.
Sourcepub unsafe fn get_ptr(&self, id: ResourceId) -> *mut u8
pub unsafe fn get_ptr(&self, id: ResourceId) -> *mut u8
Fetch a raw pointer to a resource by pre-validated index.
Intended for macro-generated dispatch code that needs direct pointer access.
§Safety
idmust have been returned byWorldBuilder::registerfor the same builder that produced this container.