bevy_ecs/message/
message_cursor.rs

1use crate::message::{
2    Message, MessageIterator, MessageIteratorWithId, MessageMutIterator, MessageMutIteratorWithId,
3    Messages,
4};
5#[cfg(feature = "multi_threaded")]
6use crate::message::{MessageMutParIter, MessageParIter};
7use core::marker::PhantomData;
8
9/// Stores the state for a [`MessageReader`] or [`MessageMutator`].
10///
11/// Access to the [`Messages<E>`] resource is required to read any incoming messages.
12///
13/// In almost all cases, you should just use a [`MessageReader`] or [`MessageMutator`],
14/// which will automatically manage the state for you.
15///
16/// However, this type can be useful if you need to manually track messages,
17/// such as when you're attempting to send and receive messages of the same type in the same system.
18///
19/// # Example
20///
21/// ```
22/// use bevy_ecs::prelude::*;
23/// use bevy_ecs::message::{Message, MessageCursor};
24///
25/// #[derive(Message, Clone, Debug)]
26/// struct MyMessage;
27///
28/// /// A system that both sends and receives messages using a [`Local`] [`MessageCursor`].
29/// fn send_and_receive_messages(
30///     // The `Local` `SystemParam` stores state inside the system itself, rather than in the world.
31///     // `MessageCursor<T>` is the internal state of `MessageMutator<T>`, which tracks which messages have been seen.
32///     mut local_message_reader: Local<MessageCursor<MyMessage>>,
33///     // We can access the `Messages` resource mutably, allowing us to both read and write its contents.
34///     mut messages: ResMut<Messages<MyMessage>>,
35/// ) {
36///     // We must collect the messages to resend, because we can't mutate messages while we're iterating over the messages.
37///     let mut messages_to_resend = Vec::new();
38///
39///     for message in local_message_reader.read(&mut messages) {
40///          messages_to_resend.push(message.clone());
41///     }
42///
43///     for message in messages_to_resend {
44///         messages.write(MyMessage);
45///     }
46/// }
47///
48/// # bevy_ecs::system::assert_is_system(send_and_receive_messages);
49/// ```
50///
51/// [`MessageReader`]: super::MessageReader
52/// [`MessageMutator`]: super::MessageMutator
53#[derive(Debug)]
54pub struct MessageCursor<E: Message> {
55    pub(super) last_message_count: usize,
56    pub(super) _marker: PhantomData<E>,
57}
58
59impl<E: Message> Default for MessageCursor<E> {
60    fn default() -> Self {
61        MessageCursor {
62            last_message_count: 0,
63            _marker: Default::default(),
64        }
65    }
66}
67
68impl<E: Message> Clone for MessageCursor<E> {
69    fn clone(&self) -> Self {
70        MessageCursor {
71            last_message_count: self.last_message_count,
72            _marker: PhantomData,
73        }
74    }
75}
76
77impl<E: Message> MessageCursor<E> {
78    /// See [`MessageReader::read`](super::MessageReader::read)
79    pub fn read<'a>(&'a mut self, messages: &'a Messages<E>) -> MessageIterator<'a, E> {
80        self.read_with_id(messages).without_id()
81    }
82
83    /// See [`MessageMutator::read`](super::MessageMutator::read)
84    pub fn read_mut<'a>(&'a mut self, messages: &'a mut Messages<E>) -> MessageMutIterator<'a, E> {
85        self.read_mut_with_id(messages).without_id()
86    }
87
88    /// See [`MessageReader::read_with_id`](super::MessageReader::read_with_id)
89    pub fn read_with_id<'a>(
90        &'a mut self,
91        messages: &'a Messages<E>,
92    ) -> MessageIteratorWithId<'a, E> {
93        MessageIteratorWithId::new(self, messages)
94    }
95
96    /// See [`MessageMutator::read_with_id`](super::MessageMutator::read_with_id)
97    pub fn read_mut_with_id<'a>(
98        &'a mut self,
99        messages: &'a mut Messages<E>,
100    ) -> MessageMutIteratorWithId<'a, E> {
101        MessageMutIteratorWithId::new(self, messages)
102    }
103
104    /// See [`MessageReader::par_read`](super::MessageReader::par_read)
105    #[cfg(feature = "multi_threaded")]
106    pub fn par_read<'a>(&'a mut self, messages: &'a Messages<E>) -> MessageParIter<'a, E> {
107        MessageParIter::new(self, messages)
108    }
109
110    /// See [`MessageMutator::par_read`](super::MessageMutator::par_read)
111    #[cfg(feature = "multi_threaded")]
112    pub fn par_read_mut<'a>(
113        &'a mut self,
114        messages: &'a mut Messages<E>,
115    ) -> MessageMutParIter<'a, E> {
116        MessageMutParIter::new(self, messages)
117    }
118
119    /// See [`MessageReader::len`](super::MessageReader::len)
120    pub fn len(&self, messages: &Messages<E>) -> usize {
121        // The number of messages in this reader is the difference between the most recent message
122        // and the last message seen by it. This will be at most the number of messages contained
123        // with the messages (any others have already been dropped)
124        // TODO: Warn when there are dropped messages, or return e.g. a `Result<usize, (usize, usize)>`
125        messages
126            .message_count
127            .saturating_sub(self.last_message_count)
128            .min(messages.len())
129    }
130
131    /// Amount of messages we missed.
132    pub fn missed_messages(&self, messages: &Messages<E>) -> usize {
133        messages
134            .oldest_message_count()
135            .saturating_sub(self.last_message_count)
136    }
137
138    /// See [`MessageReader::is_empty()`](super::MessageReader::is_empty)
139    pub fn is_empty(&self, messages: &Messages<E>) -> bool {
140        self.len(messages) == 0
141    }
142
143    /// See [`MessageReader::clear()`](super::MessageReader::clear)
144    pub fn clear(&mut self, messages: &Messages<E>) {
145        self.last_message_count = messages.message_count;
146    }
147}