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}