Skip to main content

World

Struct World 

Source
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

§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

Source

pub fn builder() -> WorldBuilder

Convenience constructor — returns a new WorldBuilder.

Source

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.

Source

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?
examples/optional_resources.rs (line 84)
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
Hide additional examples
examples/local_state.rs (line 55)
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}
examples/pipeline.rs (line 86)
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}
Source

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.

Source

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.

Source

pub fn len(&self) -> usize

Returns the number of registered resources.

Source

pub fn is_empty(&self) -> bool

Returns true if no resources are stored.

Source

pub fn contains<T: 'static>(&self) -> bool

Returns true if a resource of type T is stored.

Source

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?
examples/optional_resources.rs (line 93)
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
Hide additional examples
examples/local_state.rs (line 82)
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}
examples/pipeline.rs (line 140)
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}
Source

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.

Source

pub fn current_sequence(&self) -> Sequence

Returns the current event sequence number.

Source

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.

Source

pub unsafe fn get<T: 'static>(&self, id: ResourceId) -> &T

Fetch a shared reference to a resource by pre-validated index.

§Safety
  • id must have been returned by WorldBuilder::register for the same builder that produced this container.
  • T must be the same type that was registered at this id.
  • The caller must ensure no mutable reference to this resource exists.
Source

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
  • id must have been returned by WorldBuilder::register for the same builder that produced this container.
  • T must be the same type that was registered at this id.
  • The caller must ensure no other reference (shared or mutable) to this resource exists.
Source

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

Trait Implementations§

Auto Trait Implementations§

§

impl Freeze for World

§

impl !RefUnwindSafe for World

§

impl !Sync for World

§

impl Unpin for World

§

impl UnsafeUnpin for World

§

impl UnwindSafe for World

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.