//! [`Event`] functionality.
mod trigger;

pub use bevy_ecs_macros::{EntityEvent, Event};
pub use trigger::*;

use crate::{
    component::{Component, ComponentId},
    entity::Entity,
    world::World,
};
use core::marker::PhantomData;

/// An [`Event`] is something that "happens" at a given moment.
///
/// To make an [`Event`] "happen", you "trigger" it on a [`World`] using [`World::trigger`] or via a [`Command`](crate::system::Command)
/// using [`Commands::trigger`](crate::system::Commands::trigger). This causes any [`Observer`](crate::observer::Observer) watching for that
/// [`Event`] to run _immediately_, as part of the [`World::trigger`] call.
///
/// First, we create an [`Event`] type, typically by deriving the trait.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #
/// #[derive(Event)]
/// struct Speak {
///     message: String,
/// }
/// ```
///
/// Then, we add an [`Observer`](crate::observer::Observer) to watch for this event type:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct Speak {
/// #     message: String,
/// # }
/// #
/// # let mut world = World::new();
/// #
/// world.add_observer(|speak: On<Speak>| {
///     println!("{}", speak.message);
/// });
/// ```
///
/// Finally, we trigger the event by calling [`World::trigger`](World::trigger):
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct Speak {
/// #     message: String,
/// # }
/// #
/// # let mut world = World::new();
/// #
/// # world.add_observer(|speak: On<Speak>| {
/// #     println!("{}", speak.message);
/// # });
/// #
/// # world.flush();
/// #
/// world.trigger(Speak {
///     message: "Hello!".to_string(),
/// });
/// ```
///
/// # Triggers
///
/// Every [`Event`] has an associated [`Trigger`] implementation (set via [`Event::Trigger`]), which defines which observers will run,
/// what data will be passed to them, and the order they will be run in. Unless you are an internals developer or you have very specific
/// needs, you don't need to worry too much about [`Trigger`]. When you derive [`Event`] (or a more specific event trait like [`EntityEvent`]),
/// a [`Trigger`] will be provided for you.
///
/// The [`Event`] derive defaults [`Event::Trigger`] to [`GlobalTrigger`], which will run all observers that watch for the [`Event`].
///
/// # Entity Events
///
/// For events that "target" a specific [`Entity`], see [`EntityEvent`].
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not an `Event`",
    label = "invalid `Event`",
    note = "consider annotating `{Self}` with `#[derive(Event)]`"
)]
pub trait Event: Send + Sync + Sized + 'static {
    /// Defines which observers will run, what data will be passed to them, and the order they will be run in. See [`Trigger`] for more info.
    type Trigger<'a>: Trigger<Self>;
}

/// An [`EntityEvent`] is an [`Event`] that is triggered for a specific [`EntityEvent::event_target`] entity:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let mut world = World::default();
/// # let entity = world.spawn_empty().id();
/// #[derive(EntityEvent)]
/// struct Explode {
///     entity: Entity,
/// }
///
/// world.add_observer(|event: On<Explode>, mut commands: Commands| {
///     println!("Entity {} goes BOOM!", event.entity);
///     commands.entity(event.entity).despawn();
/// });
///
/// world.trigger(Explode { entity });
/// ```
///
/// [`EntityEvent`] will set [`EntityEvent::event_target`] automatically for named structs with an `entity` field name (as seen above). It also works for tuple structs
/// whose only field is [`Entity`]:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// struct Explode(Entity);
/// ```
///
/// The [`EntityEvent::event_target`] can also be manually set using the `#[event_target]` field attribute:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// struct Explode {
///     #[event_target]
///     exploded_entity: Entity,
/// }
/// ```
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// struct Explode(#[event_target] Entity);
/// ```
///
/// You may also use any type which implements [`ContainsEntity`](crate::entity::ContainsEntity) as the event target:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// struct Bomb(Entity);
///
/// impl ContainsEntity for Bomb {
///     fn entity(&self) -> Entity {
///         self.0
///     }
/// }
///
/// #[derive(EntityEvent)]
/// struct Explode(Bomb);
/// ```
///
/// By default, an [`EntityEvent`] is immutable. This means the event data, including the target, does not change while the event
/// is triggered. However, to support event propagation, your event must also implement the [`SetEntityEventTarget`] trait.
///
/// This trait is automatically implemented for you if you enable event propagation:
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// #[entity_event(propagate)]
/// struct Explode(Entity);
/// ```
///
/// ## Trigger Behavior
///
/// When derived, [`EntityEvent`] defaults to setting [`Event::Trigger`] to [`EntityTrigger`], which will run all normal "untargeted"
/// observers added via [`World::add_observer`], just like a default [`Event`] would (see the example above).
///
/// However it will _also_ run all observers that watch _specific_ entities, which enables you to assign entity-specific logic:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # #[derive(Component, Debug)]
/// # struct Name(String);
/// # let mut world = World::default();
/// # let e1 = world.spawn_empty().id();
/// # let e2 = world.spawn_empty().id();
/// # #[derive(EntityEvent)]
/// # struct Explode {
/// #    entity: Entity,
/// # }
/// world.entity_mut(e1).observe(|event: On<Explode>, mut commands: Commands| {
///     println!("Boom!");
///     commands.entity(event.entity).despawn();
/// });
///
/// world.entity_mut(e2).observe(|event: On<Explode>, mut commands: Commands| {
///     println!("The explosion fizzles! This entity is immune!");
/// });
/// ```
///
/// ## [`EntityEvent`] Propagation
///
/// When deriving [`EntityEvent`], you can enable "event propagation" (also known as "event bubbling") by
/// specifying the `#[entity_event(propagate)]` attribute:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// #[entity_event(propagate)]
/// struct Click {
///     entity: Entity,
/// }
/// ```
///
/// This will default to using the [`ChildOf`](crate::hierarchy::ChildOf) component to propagate the [`Event`] "up"
/// the hierarchy (from child to parent).
///
/// You can also specify your own [`Traversal`](crate::traversal::Traversal) implementation. A common pattern is to use
/// [`Relationship`](crate::relationship::Relationship) components, which will follow the relationships to their root
/// (just be sure to avoid cycles ... these aren't detected for performance reasons):
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(Component)]
/// #[relationship(relationship_target = ClickableBy)]
/// struct Clickable(Entity);
///
/// #[derive(Component)]
/// #[relationship_target(relationship = Clickable)]
/// struct ClickableBy(Vec<Entity>);
///
/// #[derive(EntityEvent)]
/// #[entity_event(propagate = &'static Clickable)]
/// struct Click {
///     entity: Entity,
/// }
/// ```
///
/// By default, propagation requires observers to opt-in:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// #[entity_event(propagate)]
/// struct Click {
///     entity: Entity,
/// }
///
/// # let mut world = World::default();
/// world.add_observer(|mut click: On<Click>| {
///   // this will propagate the event up to the parent, using `ChildOf`
///   click.propagate(true);
/// });
/// ```
///
/// But you can enable auto propagation using the `#[entity_event(auto_propagate)]` attribute:
/// ```
/// # use bevy_ecs::prelude::*;
/// #[derive(EntityEvent)]
/// #[entity_event(propagate, auto_propagate)]
/// struct Click {
///     entity: Entity,
/// }
/// ```
///
/// You can also _stop_ propagation like this:
/// ```
/// # use bevy_ecs::prelude::*;
/// # #[derive(EntityEvent)]
/// # #[entity_event(propagate)]
/// # struct Click {
/// #    entity: Entity,
/// # }
/// # fn is_finished_propagating() -> bool { true }
/// # let mut world = World::default();
/// world.add_observer(|mut click: On<Click>| {
///   if is_finished_propagating() {
///     click.propagate(false);
///   }
/// });
/// ```
///
/// ## Naming and Usage Conventions
///
/// In most cases, it is recommended to use a named struct field for the "event target" entity, and to use
/// a name that is descriptive as possible, as this makes events easier to understand and read.
///
/// For events with only one [`Entity`] field, `entity` is often a reasonable name. But if there are multiple
/// [`Entity`] fields, it is often a good idea to use a more descriptive name.
///
/// It is also generally recommended to _consume_ "event target" entities directly via their named field, as this
/// can make the context clearer, allows for more specific documentation hints in IDEs, and it generally reads better.
///
/// ## Manually spawning [`EntityEvent`] observers
///
/// The examples above that call [`EntityWorldMut::observe`] to add entity-specific observer logic are
/// just shorthand for spawning an [`Observer`] directly and manually watching the entity:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let mut world = World::default();
/// # let entity = world.spawn_empty().id();
/// # #[derive(EntityEvent)]
/// # struct Explode(Entity);
/// let mut observer = Observer::new(|event: On<Explode>| {});
/// observer.watch_entity(entity);
/// world.spawn(observer);
/// ```
///
/// Note that the [`Observer`] component is not added to the entity it is observing. Observers should always be their own entities, as there
/// can be multiple observers of the same entity!
///
/// You can call [`Observer::watch_entity`] more than once or [`Observer::watch_entities`] to watch multiple entities with the same [`Observer`].
///
/// [`EntityWorldMut::observe`]: crate::world::EntityWorldMut::observe
/// [`Observer`]: crate::observer::Observer
/// [`Observer::watch_entity`]: crate::observer::Observer::watch_entity
/// [`Observer::watch_entities`]: crate::observer::Observer::watch_entities
pub trait EntityEvent: Event {
    /// The [`Entity`] "target" of this [`EntityEvent`]. When triggered, this will run observers that watch for this specific entity.
    fn event_target(&self) -> Entity;
}

/// A trait which is used to set the target of an [`EntityEvent`].
///
/// By default, entity events are immutable; meaning their target does not change during the lifetime of the event. However, some events
/// may require mutable access to provide features such as event propagation.
///
/// You should never need to implement this trait manually if you use `#[derive(EntityEvent)]`. It is automatically implemented for you if you
/// use `#[entity_event(propagate)]`.
pub trait SetEntityEventTarget: EntityEvent {
    /// Sets the [`Entity`] "target" of this [`EntityEvent`]. When triggered, this will run observers that watch for this specific entity.
    ///
    /// Note: In general, this should not be called from within an [`Observer`](crate::observer::Observer), as this will not "retarget"
    /// the event in any of Bevy's built-in [`Trigger`] implementations.
    fn set_event_target(&mut self, entity: Entity);
}

impl World {
    /// Generates the [`EventKey`] for this event type.
    ///
    /// If this type has already been registered,
    /// this will return the existing [`EventKey`].
    ///
    /// This is used by various dynamically typed observer APIs,
    /// such as [`DeferredWorld::trigger_raw`](crate::world::DeferredWorld::trigger_raw).
    pub fn register_event_key<E: Event>(&mut self) -> EventKey {
        EventKey(self.register_component::<EventWrapperComponent<E>>())
    }

    /// Fetches the [`EventKey`] for this event type,
    /// if it has already been generated.
    ///
    /// This is used by various dynamically typed observer APIs,
    /// such as [`DeferredWorld::trigger_raw`](crate::world::DeferredWorld::trigger_raw).
    pub fn event_key<E: Event>(&self) -> Option<EventKey> {
        self.component_id::<EventWrapperComponent<E>>()
            .map(EventKey)
    }
}

/// An internal type that implements [`Component`] for a given [`Event`] type.
///
/// This exists so we can easily get access to a unique [`ComponentId`] for each [`Event`] type,
/// without requiring that [`Event`] types implement [`Component`] directly.
/// [`ComponentId`] is used internally as a unique identifier for events because they are:
///
/// - Unique to each event type.
/// - Can be quickly generated and looked up.
/// - Are compatible with dynamic event types, which aren't backed by a Rust type.
///
/// This type is an implementation detail and should never be made public.
// TODO: refactor events to store their metadata on distinct entities, rather than using `ComponentId`
#[derive(Component)]
struct EventWrapperComponent<E: Event>(PhantomData<E>);

/// A unique identifier for an [`Event`], used by [observers].
///
/// You can look up the key for your event by calling the [`World::event_key`] method.
///
/// [observers]: crate::observer
#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct EventKey(pub(crate) ComponentId);

#[cfg(test)]
mod tests {
    use alloc::{vec, vec::Vec};
    use bevy_ecs::{message::*, system::assert_is_read_only_system};
    use bevy_ecs_macros::Message;

    #[derive(Message, Copy, Clone, PartialEq, Eq, Debug)]
    struct TestEvent {
        i: usize,
    }

    #[derive(Message, Clone, PartialEq, Debug, Default)]
    struct EmptyTestEvent;

    fn get_events<E: Message + Clone>(
        events: &Messages<E>,
        cursor: &mut MessageCursor<E>,
    ) -> Vec<E> {
        cursor.read(events).cloned().collect::<Vec<E>>()
    }

    #[test]
    fn test_events() {
        let mut events = Messages::<TestEvent>::default();
        let event_0 = TestEvent { i: 0 };
        let event_1 = TestEvent { i: 1 };
        let event_2 = TestEvent { i: 2 };

        // this reader will miss event_0 and event_1 because it wont read them over the course of
        // two updates
        let mut reader_missed: MessageCursor<TestEvent> = events.get_cursor();

        let mut reader_a: MessageCursor<TestEvent> = events.get_cursor();

        events.write(event_0);

        assert_eq!(
            get_events(&events, &mut reader_a),
            vec![event_0],
            "reader_a created before event receives event"
        );
        assert_eq!(
            get_events(&events, &mut reader_a),
            vec![],
            "second iteration of reader_a created before event results in zero events"
        );

        let mut reader_b: MessageCursor<TestEvent> = events.get_cursor();

        assert_eq!(
            get_events(&events, &mut reader_b),
            vec![event_0],
            "reader_b created after event receives event"
        );
        assert_eq!(
            get_events(&events, &mut reader_b),
            vec![],
            "second iteration of reader_b created after event results in zero events"
        );

        events.write(event_1);

        let mut reader_c = events.get_cursor();

        assert_eq!(
            get_events(&events, &mut reader_c),
            vec![event_0, event_1],
            "reader_c created after two events receives both events"
        );
        assert_eq!(
            get_events(&events, &mut reader_c),
            vec![],
            "second iteration of reader_c created after two event results in zero events"
        );

        assert_eq!(
            get_events(&events, &mut reader_a),
            vec![event_1],
            "reader_a receives next unread event"
        );

        events.update();

        let mut reader_d = events.get_cursor();

        events.write(event_2);

        assert_eq!(
            get_events(&events, &mut reader_a),
            vec![event_2],
            "reader_a receives event created after update"
        );
        assert_eq!(
            get_events(&events, &mut reader_b),
            vec![event_1, event_2],
            "reader_b receives events created before and after update"
        );
        assert_eq!(
            get_events(&events, &mut reader_d),
            vec![event_0, event_1, event_2],
            "reader_d receives all events created before and after update"
        );

        events.update();

        assert_eq!(
            get_events(&events, &mut reader_missed),
            vec![event_2],
            "reader_missed missed events unread after two update() calls"
        );
    }

    // Events Collection
    fn events_clear_and_read_impl(clear_func: impl FnOnce(&mut Messages<TestEvent>)) {
        let mut events = Messages::<TestEvent>::default();
        let mut reader = events.get_cursor();

        assert!(reader.read(&events).next().is_none());

        events.write(TestEvent { i: 0 });
        assert_eq!(*reader.read(&events).next().unwrap(), TestEvent { i: 0 });
        assert_eq!(reader.read(&events).next(), None);

        events.write(TestEvent { i: 1 });
        clear_func(&mut events);
        assert!(reader.read(&events).next().is_none());

        events.write(TestEvent { i: 2 });
        events.update();
        events.write(TestEvent { i: 3 });

        assert!(reader
            .read(&events)
            .eq([TestEvent { i: 2 }, TestEvent { i: 3 }].iter()));
    }

    #[test]
    fn test_events_clear_and_read() {
        events_clear_and_read_impl(Messages::clear);
    }

    #[test]
    fn test_events_drain_and_read() {
        events_clear_and_read_impl(|events| {
            assert!(events
                .drain()
                .eq(vec![TestEvent { i: 0 }, TestEvent { i: 1 }].into_iter()));
        });
    }

    #[test]
    fn test_events_write_default() {
        let mut events = Messages::<EmptyTestEvent>::default();
        events.write_default();

        let mut reader = events.get_cursor();
        assert_eq!(get_events(&events, &mut reader), vec![EmptyTestEvent]);
    }

    #[test]
    fn test_write_events_ids() {
        let mut events = Messages::<TestEvent>::default();
        let event_0 = TestEvent { i: 0 };
        let event_1 = TestEvent { i: 1 };
        let event_2 = TestEvent { i: 2 };

        let event_0_id = events.write(event_0);

        assert_eq!(
            events.get_message(event_0_id.id),
            Some((&event_0, event_0_id)),
            "Getting a sent event by ID should return the original event"
        );

        let mut event_ids = events.write_batch([event_1, event_2]);

        let event_id = event_ids.next().expect("Event 1 must have been sent");

        assert_eq!(
            events.get_message(event_id.id),
            Some((&event_1, event_id)),
            "Getting a sent event by ID should return the original event"
        );

        let event_id = event_ids.next().expect("Event 2 must have been sent");

        assert_eq!(
            events.get_message(event_id.id),
            Some((&event_2, event_id)),
            "Getting a sent event by ID should return the original event"
        );

        assert!(
            event_ids.next().is_none(),
            "Only sent two events; got more than two IDs"
        );
    }

    #[test]
    fn test_event_registry_can_add_and_remove_events_to_world() {
        use bevy_ecs::prelude::*;

        let mut world = World::new();
        MessageRegistry::register_message::<TestEvent>(&mut world);

        let has_events = world.get_resource::<Messages<TestEvent>>().is_some();
        assert!(has_events, "Should have the events resource");

        MessageRegistry::deregister_messages::<TestEvent>(&mut world);

        let has_events = world.get_resource::<Messages<TestEvent>>().is_some();
        assert!(!has_events, "Should not have the events resource");
    }

    #[test]
    fn test_events_update_drain() {
        let mut events = Messages::<TestEvent>::default();
        let mut reader = events.get_cursor();

        events.write(TestEvent { i: 0 });
        events.write(TestEvent { i: 1 });
        assert_eq!(reader.read(&events).count(), 2);

        let mut old_events = Vec::from_iter(events.update_drain());
        assert!(old_events.is_empty());

        events.write(TestEvent { i: 2 });
        assert_eq!(reader.read(&events).count(), 1);

        old_events.extend(events.update_drain());
        assert_eq!(old_events.len(), 2);

        old_events.extend(events.update_drain());
        assert_eq!(
            old_events,
            &[TestEvent { i: 0 }, TestEvent { i: 1 }, TestEvent { i: 2 }]
        );
    }

    #[test]
    fn test_events_empty() {
        let mut events = Messages::<TestEvent>::default();
        assert!(events.is_empty());

        events.write(TestEvent { i: 0 });
        assert!(!events.is_empty());

        events.update();
        assert!(!events.is_empty());

        // events are only empty after the second call to update
        // due to double buffering.
        events.update();
        assert!(events.is_empty());
    }

    #[test]
    fn test_events_extend_impl() {
        let mut events = Messages::<TestEvent>::default();
        let mut reader = events.get_cursor();

        events.extend(vec![TestEvent { i: 0 }, TestEvent { i: 1 }]);
        assert!(reader
            .read(&events)
            .eq([TestEvent { i: 0 }, TestEvent { i: 1 }].iter()));
    }

    // Cursor
    #[test]
    fn test_event_cursor_read() {
        let mut events = Messages::<TestEvent>::default();
        let mut cursor = events.get_cursor();
        assert!(cursor.read(&events).next().is_none());

        events.write(TestEvent { i: 0 });
        let sent_event = cursor.read(&events).next().unwrap();
        assert_eq!(sent_event, &TestEvent { i: 0 });
        assert!(cursor.read(&events).next().is_none());

        events.write(TestEvent { i: 2 });
        let sent_event = cursor.read(&events).next().unwrap();
        assert_eq!(sent_event, &TestEvent { i: 2 });
        assert!(cursor.read(&events).next().is_none());

        events.clear();
        assert!(cursor.read(&events).next().is_none());
    }

    #[test]
    fn test_event_cursor_read_mut() {
        let mut events = Messages::<TestEvent>::default();
        let mut write_cursor = events.get_cursor();
        let mut read_cursor = events.get_cursor();
        assert!(write_cursor.read_mut(&mut events).next().is_none());
        assert!(read_cursor.read(&events).next().is_none());

        events.write(TestEvent { i: 0 });
        let sent_event = write_cursor.read_mut(&mut events).next().unwrap();
        assert_eq!(sent_event, &mut TestEvent { i: 0 });
        *sent_event = TestEvent { i: 1 }; // Mutate whole event
        assert_eq!(
            read_cursor.read(&events).next().unwrap(),
            &TestEvent { i: 1 }
        );
        assert!(read_cursor.read(&events).next().is_none());

        events.write(TestEvent { i: 2 });
        let sent_event = write_cursor.read_mut(&mut events).next().unwrap();
        assert_eq!(sent_event, &mut TestEvent { i: 2 });
        sent_event.i = 3; // Mutate sub value
        assert_eq!(
            read_cursor.read(&events).next().unwrap(),
            &TestEvent { i: 3 }
        );
        assert!(read_cursor.read(&events).next().is_none());

        events.clear();
        assert!(write_cursor.read(&events).next().is_none());
        assert!(read_cursor.read(&events).next().is_none());
    }

    #[test]
    fn test_event_cursor_clear() {
        let mut events = Messages::<TestEvent>::default();
        let mut reader = events.get_cursor();

        events.write(TestEvent { i: 0 });
        assert_eq!(reader.len(&events), 1);
        reader.clear(&events);
        assert_eq!(reader.len(&events), 0);
    }

    #[test]
    fn test_event_cursor_len_update() {
        let mut events = Messages::<TestEvent>::default();
        events.write(TestEvent { i: 0 });
        events.write(TestEvent { i: 0 });
        let reader = events.get_cursor();
        assert_eq!(reader.len(&events), 2);
        events.update();
        events.write(TestEvent { i: 0 });
        assert_eq!(reader.len(&events), 3);
        events.update();
        assert_eq!(reader.len(&events), 1);
        events.update();
        assert!(reader.is_empty(&events));
    }

    #[test]
    fn test_event_cursor_len_current() {
        let mut events = Messages::<TestEvent>::default();
        events.write(TestEvent { i: 0 });
        let reader = events.get_cursor_current();
        assert!(reader.is_empty(&events));
        events.write(TestEvent { i: 0 });
        assert_eq!(reader.len(&events), 1);
        assert!(!reader.is_empty(&events));
    }

    #[test]
    fn test_event_cursor_iter_len_updated() {
        let mut events = Messages::<TestEvent>::default();
        events.write(TestEvent { i: 0 });
        events.write(TestEvent { i: 1 });
        events.write(TestEvent { i: 2 });
        let mut reader = events.get_cursor();
        let mut iter = reader.read(&events);
        assert_eq!(iter.len(), 3);
        iter.next();
        assert_eq!(iter.len(), 2);
        iter.next();
        assert_eq!(iter.len(), 1);
        iter.next();
        assert_eq!(iter.len(), 0);
    }

    #[test]
    fn test_event_cursor_len_empty() {
        let events = Messages::<TestEvent>::default();
        assert_eq!(events.get_cursor().len(&events), 0);
        assert!(events.get_cursor().is_empty(&events));
    }

    #[test]
    fn test_event_cursor_len_filled() {
        let mut events = Messages::<TestEvent>::default();
        events.write(TestEvent { i: 0 });
        assert_eq!(events.get_cursor().len(&events), 1);
        assert!(!events.get_cursor().is_empty(&events));
    }

    #[cfg(feature = "multi_threaded")]
    #[test]
    fn test_event_cursor_par_read() {
        use crate::prelude::*;
        use core::sync::atomic::{AtomicUsize, Ordering};

        #[derive(Resource)]
        struct Counter(AtomicUsize);

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();
        for _ in 0..100 {
            world.write_message(TestEvent { i: 1 });
        }

        let mut schedule = Schedule::default();

        schedule.add_systems(
            |mut cursor: Local<MessageCursor<TestEvent>>,
             events: Res<Messages<TestEvent>>,
             counter: ResMut<Counter>| {
                cursor.par_read(&events).for_each(|event| {
                    counter.0.fetch_add(event.i, Ordering::Relaxed);
                });
            },
        );

        world.insert_resource(Counter(AtomicUsize::new(0)));
        schedule.run(&mut world);
        let counter = world.remove_resource::<Counter>().unwrap();
        assert_eq!(counter.0.into_inner(), 100);

        world.insert_resource(Counter(AtomicUsize::new(0)));
        schedule.run(&mut world);
        let counter = world.remove_resource::<Counter>().unwrap();
        assert_eq!(
            counter.0.into_inner(),
            0,
            "par_read should have consumed events but didn't"
        );
    }

    #[cfg(feature = "multi_threaded")]
    #[test]
    fn test_event_cursor_par_read_mut() {
        use crate::prelude::*;
        use core::sync::atomic::{AtomicUsize, Ordering};

        #[derive(Resource)]
        struct Counter(AtomicUsize);

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();
        for _ in 0..100 {
            world.write_message(TestEvent { i: 1 });
        }
        let mut schedule = Schedule::default();
        schedule.add_systems(
            |mut cursor: Local<MessageCursor<TestEvent>>,
             mut events: ResMut<Messages<TestEvent>>,
             counter: ResMut<Counter>| {
                cursor.par_read_mut(&mut events).for_each(|event| {
                    event.i += 1;
                    counter.0.fetch_add(event.i, Ordering::Relaxed);
                });
            },
        );
        world.insert_resource(Counter(AtomicUsize::new(0)));
        schedule.run(&mut world);
        let counter = world.remove_resource::<Counter>().unwrap();
        assert_eq!(counter.0.into_inner(), 200, "Initial run failed");

        world.insert_resource(Counter(AtomicUsize::new(0)));
        schedule.run(&mut world);
        let counter = world.remove_resource::<Counter>().unwrap();
        assert_eq!(
            counter.0.into_inner(),
            0,
            "par_read_mut should have consumed events but didn't"
        );
    }

    // Reader & Mutator
    #[test]
    fn ensure_reader_readonly() {
        fn reader_system(_: MessageReader<EmptyTestEvent>) {}

        assert_is_read_only_system(reader_system);
    }

    #[test]
    fn test_event_reader_iter_last() {
        use bevy_ecs::prelude::*;

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();

        let mut reader = IntoSystem::into_system(
            |mut events: MessageReader<TestEvent>| -> Option<TestEvent> {
                events.read().last().copied()
            },
        );
        reader.initialize(&mut world);

        let last = reader.run((), &mut world).unwrap();
        assert!(last.is_none(), "MessageReader should be empty");

        world.write_message(TestEvent { i: 0 });
        let last = reader.run((), &mut world).unwrap();
        assert_eq!(last, Some(TestEvent { i: 0 }));

        world.write_message(TestEvent { i: 1 });
        world.write_message(TestEvent { i: 2 });
        world.write_message(TestEvent { i: 3 });
        let last = reader.run((), &mut world).unwrap();
        assert_eq!(last, Some(TestEvent { i: 3 }));

        let last = reader.run((), &mut world).unwrap();
        assert!(last.is_none(), "MessageReader should be empty");
    }

    #[test]
    fn test_event_mutator_iter_last() {
        use bevy_ecs::prelude::*;

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();

        let mut mutator = IntoSystem::into_system(
            |mut events: MessageMutator<TestEvent>| -> Option<TestEvent> {
                events.read().last().copied()
            },
        );
        mutator.initialize(&mut world);

        let last = mutator.run((), &mut world).unwrap();
        assert!(last.is_none(), "EventMutator should be empty");

        world.write_message(TestEvent { i: 0 });
        let last = mutator.run((), &mut world).unwrap();
        assert_eq!(last, Some(TestEvent { i: 0 }));

        world.write_message(TestEvent { i: 1 });
        world.write_message(TestEvent { i: 2 });
        world.write_message(TestEvent { i: 3 });
        let last = mutator.run((), &mut world).unwrap();
        assert_eq!(last, Some(TestEvent { i: 3 }));

        let last = mutator.run((), &mut world).unwrap();
        assert!(last.is_none(), "EventMutator should be empty");
    }

    #[test]
    fn test_event_reader_iter_nth() {
        use bevy_ecs::prelude::*;

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();

        world.write_message(TestEvent { i: 0 });
        world.write_message(TestEvent { i: 1 });
        world.write_message(TestEvent { i: 2 });
        world.write_message(TestEvent { i: 3 });
        world.write_message(TestEvent { i: 4 });

        let mut schedule = Schedule::default();
        schedule.add_systems(|mut events: MessageReader<TestEvent>| {
            let mut iter = events.read();

            assert_eq!(iter.next(), Some(&TestEvent { i: 0 }));
            assert_eq!(iter.nth(2), Some(&TestEvent { i: 3 }));
            assert_eq!(iter.nth(1), None);

            assert!(events.is_empty());
        });
        schedule.run(&mut world);
    }

    #[test]
    fn test_event_mutator_iter_nth() {
        use bevy_ecs::prelude::*;

        let mut world = World::new();
        world.init_resource::<Messages<TestEvent>>();

        world.write_message(TestEvent { i: 0 });
        world.write_message(TestEvent { i: 1 });
        world.write_message(TestEvent { i: 2 });
        world.write_message(TestEvent { i: 3 });
        world.write_message(TestEvent { i: 4 });

        let mut schedule = Schedule::default();
        schedule.add_systems(|mut events: MessageReader<TestEvent>| {
            let mut iter = events.read();

            assert_eq!(iter.next(), Some(&TestEvent { i: 0 }));
            assert_eq!(iter.nth(2), Some(&TestEvent { i: 3 }));
            assert_eq!(iter.nth(1), None);

            assert!(events.is_empty());
        });
        schedule.run(&mut world);
    }

    #[test]
    fn test_derive_entity_event() {
        use bevy_ecs::prelude::*;

        struct Entitoid(Entity);

        impl ContainsEntity for Entitoid {
            fn entity(&self) -> Entity {
                self.0
            }
        }

        struct MutableEntitoid(Entity);

        impl ContainsEntity for MutableEntitoid {
            fn entity(&self) -> Entity {
                self.0
            }
        }

        impl From<Entity> for MutableEntitoid {
            fn from(value: Entity) -> Self {
                Self(value)
            }
        }

        #[derive(EntityEvent)]
        struct A(Entity);

        #[derive(EntityEvent)]
        #[entity_event(propagate)]
        struct AP(Entity);

        #[derive(EntityEvent)]
        struct B {
            entity: Entity,
        }

        #[derive(EntityEvent)]
        #[entity_event(propagate)]
        struct BP {
            entity: Entity,
        }

        #[derive(EntityEvent)]
        struct C {
            #[event_target]
            target: Entity,
        }

        #[derive(EntityEvent)]
        #[entity_event(propagate)]
        struct CP {
            #[event_target]
            target: Entity,
        }

        #[derive(EntityEvent)]
        struct D(Entitoid);

        // SHOULD NOT COMPILE:
        // #[derive(EntityEvent)]
        // #[entity_event(propagate)]
        // struct DP(Entitoid);

        #[derive(EntityEvent)]
        struct E {
            entity: Entitoid,
        }

        // SHOULD NOT COMPILE:
        // #[derive(EntityEvent)]
        // #[entity_event(propagate)]
        // struct EP {
        //     entity: Entitoid,
        // }

        #[derive(EntityEvent)]
        struct F {
            #[event_target]
            target: Entitoid,
        }

        // SHOULD NOT COMPILE:
        // #[derive(EntityEvent)]
        // #[entity_event(propagate)]
        // struct FP {
        //     #[event_target]
        //     target: Entitoid,
        // }

        #[derive(EntityEvent)]
        #[entity_event(propagate)]
        struct G(MutableEntitoid);

        impl From<Entity> for G {
            fn from(value: Entity) -> Self {
                Self(value.into())
            }
        }

        let mut world = World::new();
        let entity = world.spawn_empty().id();

        world.entity_mut(entity).trigger(A);
        world.entity_mut(entity).trigger(AP);
        world.trigger(B { entity });
        world.trigger(BP { entity });
        world.trigger(C { target: entity });
        world.trigger(CP { target: entity });
        world.trigger(D(Entitoid(entity)));
        world.trigger(E {
            entity: Entitoid(entity),
        });
        world.trigger(F {
            target: Entitoid(entity),
        });
        world.trigger(G(MutableEntitoid(entity)));
        world.entity_mut(entity).trigger(G::from);

        // No asserts; test just needs to compile
    }
}

Homonyms

cyberia/src/components/mod.rs
cyberia/src/pages/mod.rs
cyb/optica/src/output/mod.rs
neural/trident/src/compile/mod.rs
cyb/optica/src/parser/mod.rs
soft3/nox/rs/data/mod.rs
neural/trident/src/api/mod.rs
soft3/mir/src/graph/mod.rs
cyb/optica/src/render/mod.rs
cyb/optica/src/scanner/mod.rs
soft3/cybergraph/tests/common/mod.rs
neural/trident/src/verify/mod.rs
soft3/tru/rs/model/mod.rs
neural/trident/src/diagnostic/mod.rs
soft3/mudra/src/proof/mod.rs
cyb/optica/src/graph/mod.rs
soft3/glia/import/loader/mod.rs
soft3/glia/run/backend/mod.rs
neural/trident/src/import/mod.rs
soft3/tru/rs/pass/mod.rs
soft3/mir/src/bevy/mod.rs
neural/trident/src/package/mod.rs
neural/trident/src/lsp/mod.rs
neural/trident/src/field/mod.rs
cyb/prysm/atoms/rs/mod.rs
soft3/tru/rs/graph/mod.rs
neural/trident/src/deploy/mod.rs
soft3/mir/src/epoch/mod.rs
neural/trident/src/runtime/mod.rs
soft3/glia/run/arch/mod.rs
neural/trident/src/typecheck/mod.rs
neural/trident/src/gpu/mod.rs
soft3/nox/rs/jets/mod.rs
soft3/glia/run/tokenizer/mod.rs
soft3/mir/src/frame/mod.rs
neural/trident/src/ir/mod.rs
neural/trident/src/config/mod.rs
soft3/nox/rs/patterns/mod.rs
neural/trident/src/cost/mod.rs
soft3/glia/run/ir/mod.rs
neural/trident/src/cli/mod.rs
soft3/tru/rs/focusing/mod.rs
neural/trident/src/neural/mod.rs
cyb/optica/src/query/mod.rs
cyb/prysm/system/rs/mod.rs
neural/trident/src/ast/mod.rs
soft3/glia/run/bench/mod.rs
cyb/prysm/molecules/rs/mod.rs
cyb/optica/src/server/mod.rs
soft3/glia/run/core/mod.rs
neural/trident/src/syntax/mod.rs
cyb/honeycrisp/acpu/src/vector/mod.rs
soft3/glia/run/backend/cpu/mod.rs
soft3/zheng/rs/src/spartan/mod.rs
soft3/bbg/rs/src/storage/mod.rs
neural/trident/src/config/resolve/mod.rs
cyb/honeycrisp/aruminium/src/ffi/mod.rs
cyb/cyb/cyb-shell/src/worlds/mod.rs
cyb/wysm/crates/wasi/tests/mod.rs
soft3/zheng/rs/src/ccs/mod.rs
neural/trident/src/package/store/mod.rs
cyb/cyb/cyb-shell/src/shell/mod.rs
cyb/wysm/crates/wasmi/tests/mod.rs
neural/trident/src/verify/synthesize/mod.rs
cyb/honeycrisp/acpu/src/field/mod.rs
neural/rs/macros/src/addressed/mod.rs
soft3/glia/run/cli/cmd/mod.rs
neural/trident/src/cost/stack_verifier/mod.rs
neural/eidos/rs/src/stdlib/mod.rs
neural/trident/src/verify/sym/mod.rs
neural/trident/src/syntax/format/mod.rs
neural/trident/src/syntax/grammar/mod.rs
neural/trident/src/lsp/util/mod.rs
neural/rs/rsc/src/lints/mod.rs
neural/trident/src/typecheck/tests/mod.rs
neural/eidos/rs/src/surface/mod.rs
soft3/mir/src/frame/tiers/mod.rs
cyb/honeycrisp/acpu/src/pulse/mod.rs
neural/trident/src/ir/lir/mod.rs
neural/trident/src/package/registry/mod.rs
neural/trident/src/neural/model/mod.rs
neural/trident/src/package/hash/mod.rs
cyb/honeycrisp/acpu/src/sync/mod.rs
soft3/glia/run/arch/decoder/mod.rs
neural/trident/src/verify/report/mod.rs
neural/trident/src/ir/tir/mod.rs
cyb/honeycrisp/rane/src/mil/mod.rs
cyb/honeycrisp/acpu/src/crypto/mod.rs
soft3/zheng/rs/src/folding/mod.rs
neural/trident/src/ir/tree/mod.rs
cyb/honeycrisp/acpu/src/matrix/mod.rs
soft3/glia/run/backend/honeycrisp/mod.rs
neural/eidos/rs/src/elab/mod.rs
neural/rs/macros/src/registers/mod.rs
neural/trident/src/verify/solve/mod.rs
neural/rs/core/src/fixed_point/mod.rs
neural/trident/src/syntax/parser/mod.rs
neural/trident/src/neural/data/mod.rs
neural/trident/src/verify/smt/mod.rs
soft3/radio/iroh-blobs/examples/common/mod.rs
soft3/strata/nebu/rs/extension/mod.rs
neural/rs/darwin-sys/src/ffi/mod.rs
cyb/honeycrisp/acpu/src/sparse/mod.rs
soft3/glia/run/backend/wgpu/mod.rs
neural/rs/core/src/bounded/mod.rs
neural/eidos/rs/src/tactic_ext/mod.rs
neural/trident/src/cost/model/mod.rs
cyb/wysm/crates/wast/tests/mod.rs
soft3/radio/iroh-blobs/src/store/mod.rs
neural/trident/src/package/manifest/mod.rs
cyb/cyb/cyb-shell/src/agent/mod.rs
neural/trident/src/neural/training/mod.rs
neural/trident/src/verify/equiv/mod.rs
neural/trident/src/syntax/lexer/mod.rs
cyb/honeycrisp/acpu/src/numeric/mod.rs
soft3/radio/cyber-bao/src/io/mod.rs
neural/trident/src/ir/kir/mod.rs
cyb/honeycrisp/aruminium/src/render/mod.rs
neural/trident/src/neural/inference/mod.rs
cyb/honeycrisp/acpu/src/probe/mod.rs
neural/trident/src/api/tests/mod.rs
cyb/honeycrisp/acpu/src/gemm/mod.rs
soft3/nox/rs/jets/backends/mod.rs
neural/trident/src/lsp/semantic/mod.rs
neural/rs/macros/src/cell/mod.rs
neural/trident/src/config/scaffold/mod.rs
soft3/zheng/rs/src/sumcheck/mod.rs
cyb/evy/forks/bevy_ecs/src/entity/mod.rs
neural/trident/src/ir/tir/builder/mod.rs
cyb/evy/forks/bevy_ecs/src/system/mod.rs
cyb/evy/forks/bevy_sprite_render/src/render/mod.rs
soft3/strata/jali/wgsl/src/shaders/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/tonemapping/mod.rs
cyb/evy/forks/bevy_anti_alias/src/dlss/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/skybox/mod.rs
cyb/evy/forks/bevy_sprite_render/src/text2d/mod.rs
cyb/evy/forks/bevy_render/src/batching/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/experimental/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/oit/mod.rs
cyb/evy/forks/bevy_sprite_render/src/tilemap_chunk/mod.rs
cyb/evy/forks/bevy_pbr/src/atmosphere/mod.rs
cyb/evy/forks/bevy_post_process/src/motion_blur/mod.rs
cyb/wysm/crates/wasmi/src/store/mod.rs
cyb/evy/forks/bevy_render/src/render_graph/mod.rs
cyb/wysm/crates/wasmi/benches/bench/mod.rs
cyb/evy/forks/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs
neural/trident/src/ir/tir/stack/mod.rs
cyb/evy/forks/bevy_render/src/texture/mod.rs
cyb/wysm/crates/c_api/src/types/mod.rs
soft3/strata/genies/wgsl/src/shaders/mod.rs
cyb/wysm/crates/core/src/memory/mod.rs
bootloader/go-cyber/mcp/rust/src/proto/mod.rs
cyb/evy/forks/bevy_ecs/src/bundle/mod.rs
cyb/evy/forks/bevy_mesh/src/primitives/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/mod.rs
cyb/wysm/crates/wasmi/src/module/mod.rs
cyb/evy/forks/bevy_sprite/src/texture_slice/mod.rs
cyb/evy/forks/bevy_ecs/src/observer/mod.rs
neural/trident/src/ir/tir/neural/mod.rs
cyb/evy/forks/bevy_render/src/view/mod.rs
neural/trident/src/ir/lir/lower/mod.rs
cyb/evy/forks/bevy_anti_alias/src/smaa/mod.rs
bootloader/go-cyber/mcp/rust/src/clients/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/fullscreen_vertex_shader/mod.rs
cyb/wysm/crates/wasmi/tests/integration/mod.rs
cyb/wysm/crates/ir/src/decode/mod.rs
cyb/wysm/crates/wasmi/src/memory/mod.rs
cyb/evy/crates/evy_prysm_core/src/layout/mod.rs
cyb/evy/forks/bevy_anti_alias/src/fxaa/mod.rs
cyb/evy/forks/bevy_pbr/src/prepass/mod.rs
cyb/evy/forks/bevy_render/src/render_resource/mod.rs
cyb/evy/forks/bevy_ecs/src/query/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/core_2d/mod.rs
cyb/wysm/crates/cli/src/commands/mod.rs
cyb/evy/forks/bevy_render/src/renderer/mod.rs
cyb/wysm/crates/collections/src/arena/mod.rs
cyb/evy/forks/bevy_post_process/src/effect_stack/mod.rs
cyb/evy/forks/bevy_ecs/src/change_detection/mod.rs
cyb/evy/forks/bevy_pbr/src/ssao/mod.rs
cyb/evy/forks/naga/src/keywords/mod.rs
cyb/evy/forks/naga/src/compact/mod.rs
neural/trident/src/ir/tir/lower/mod.rs
cyb/evy/forks/bevy_pbr/src/render/mod.rs
cyb/evy/forks/bevy_ecs/src/world/mod.rs
cyb/evy/forks/bevy_anti_alias/src/taa/mod.rs
cyb/evy/forks/bevy_ecs/src/reflect/mod.rs
soft3/strata/kuro/wgsl/src/shaders/mod.rs
cyb/evy/forks/bevy_ecs/src/error/mod.rs
neural/trident/src/ir/kir/lower/mod.rs
cyb/evy/forks/naga/src/proc/mod.rs
cyb/evy/forks/bevy_ecs/src/component/mod.rs
cyb/evy/forks/bevy_sprite_render/src/mesh2d/mod.rs
cyb/evy/forks/bevy_ecs/src/relationship/mod.rs
cyb/wysm/crates/wasmi/src/instance/mod.rs
cyb/evy/forks/bevy_pbr/src/ssr/mod.rs
bootloader/go-cyber/mcp/rust/src/tools/mod.rs
soft3/glia/run/backend/honeycrisp/kernels/mod.rs
cyb/evy/forks/naga/src/back/mod.rs
soft3/glia/run/backend/cpu/quant/mod.rs
cyb/wysm/crates/core/src/table/mod.rs
cyb/evy/forks/bevy_post_process/src/dof/mod.rs
cyb/evy/forks/bevy_pbr/src/light_probe/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/prepass/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/upscaling/mod.rs
cyb/wysm/crates/wasmi/src/table/mod.rs
cyb/evy/forks/bevy_post_process/src/bloom/mod.rs
cyb/evy/forks/bevy_pbr/src/lightmap/mod.rs
neural/trident/src/ir/tir/optimize/mod.rs
cyb/evy/forks/bevy_gizmos/src/primitives/mod.rs
cyb/evy/forks/bevy_post_process/src/auto_exposure/mod.rs
neural/trident/src/neural/data/tir_graph/mod.rs
cyb/evy/forks/bevy_render/src/experimental/mod.rs
cyb/wysm/crates/wasmi/src/engine/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/deferred/mod.rs
cyb/evy/forks/naga/src/arena/mod.rs
cyb/evy/forks/bevy_render/src/diagnostic/mod.rs
cyb/evy/forks/bevy_render/src/render_phase/mod.rs
cyb/evy/forks/bevy_transform/src/components/mod.rs
soft3/strata/trop/wgsl/src/shaders/mod.rs
soft3/glia/run/backend/wgpu/kernels/mod.rs
cyb/evy/forks/bevy_sprite_render/src/texture_slice/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/core_3d/mod.rs
cyb/evy/forks/bevy_render/src/mesh/mod.rs
neural/trident/src/ir/tree/lower/mod.rs
cyb/evy/forks/bevy_pbr/src/volumetric_fog/mod.rs
cyb/evy/forks/bevy_pbr/src/decal/mod.rs
cyb/wysm/crates/fuzz/src/oracle/mod.rs
cyb/evy/forks/bevy_ecs/src/message/mod.rs
cyb/evy/forks/naga/src/valid/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/blit/mod.rs
cyb/evy/forks/naga/src/front/mod.rs
cyb/wysm/crates/wasi/src/sync/mod.rs
cyb/evy/forks/bevy_pbr/src/meshlet/mod.rs
cyb/evy/forks/bevy_pbr/src/deferred/mod.rs
neural/trident/src/syntax/parser/tests/mod.rs
cyb/evy/forks/bevy_ecs/src/storage/mod.rs
cyb/evy/forks/bevy_tasks/src/iter/mod.rs
soft3/glia/run/arch/decoder/families/mod.rs
cyb/wysm/crates/wasmi/src/func/mod.rs
cyb/evy/forks/naga/src/common/mod.rs
cyb/evy/forks/naga/src/front/wgsl/mod.rs
cyb/evy/forks/naga/src/back/spv/mod.rs
cyb/evy/forks/naga/src/back/dot/mod.rs
cyb/evy/forks/bevy_render/src/view/window/mod.rs
cyb/wysm/crates/wasi/src/sync/snapshots/mod.rs
cyb/evy/forks/bevy_render/src/experimental/occlusion_culling/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/graph/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/mod.rs
cyb/wysm/crates/wasmi/src/module/parser/mod.rs
cyb/wysm/crates/wasmi/src/engine/limits/mod.rs
cyb/wysm/crates/wasmi/src/engine/executor/mod.rs
cyb/evy/forks/bevy_ecs/src/system/commands/mod.rs
cyb/evy/forks/naga/src/back/wgsl/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/oit/resolve/mod.rs
cyb/wysm/crates/wasmi/src/module/instantiate/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/experimental/mip_generation/mod.rs
cyb/evy/forks/bevy_ecs/src/storage/table/mod.rs
bootloader/go-cyber/cw/packages/cyber-std/src/tokenfactory/mod.rs
cyb/evy/forks/bevy_render/src/view/visibility/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/executor/mod.rs
cyb/evy/forks/naga/src/front/spv/mod.rs
cyb/evy/forks/naga/src/back/msl/mod.rs
cyb/evy/forks/naga/src/front/glsl/mod.rs
cyb/evy/forks/bevy_ecs/src/world/entity_access/mod.rs
cyb/evy/forks/bevy_mesh/src/primitives/dim3/mod.rs
cyb/evy/forks/naga/src/back/glsl/mod.rs
cyb/evy/forks/naga/src/back/hlsl/mod.rs
struct Baz { m: mat3x2, } struct Baz { float2 m_0; float2 m_1; float2 m_2; }; float3x2 GetMatmOnBaz(Baz obj) { return float3x2(obj.m_0, obj.m_1, obj.m_2); }
cyb/wysm/crates/wasmi/src/engine/executor/handler/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/mod.rs
cyb/evy/forks/naga/src/front/wgsl/parse/mod.rs
cyb/evy/forks/naga/src/back/wgsl/polyfill/mod.rs
cyb/evy/forks/naga/src/front/wgsl/lower/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/simd/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/stack/mod.rs
cyb/wysm/crates/wasmi/src/engine/executor/handler/dispatch/mod.rs

Graph