--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hedgewars-engine-messages/src/queue.rs Fri Aug 02 13:35:23 2019 +0200
@@ -0,0 +1,112 @@
+use crate::messages::{EngineMessage::*, SyncedEngineMessage::*, UnsyncedEngineMessage::*, *};
+use queues::*;
+
+#[derive(PartialEq)]
+pub enum QueueChatStrategy {
+ NetworkGame,
+ LocalGame,
+}
+
+pub struct MessagesQueue {
+ strategy: QueueChatStrategy,
+ hi_ticks: u32,
+ unordered: Queue<EngineMessage>,
+ ordered: Queue<EngineMessage>,
+}
+
+impl MessagesQueue {
+ pub fn new(strategy: QueueChatStrategy) -> Self {
+ MessagesQueue {
+ strategy,
+ hi_ticks: 0,
+ unordered: queue![],
+ ordered: queue![],
+ }
+ }
+
+ fn is_unordered(&self, message: &EngineMessage) -> bool {
+ match message {
+ Unordered(_) => true,
+ Unsynced(HogSay(_)) | Unsynced(ChatMessage(_)) | Unsynced(TeamMessage(_)) => {
+ self.strategy == QueueChatStrategy::NetworkGame
+ }
+ _ => false,
+ }
+ }
+
+ pub fn push(&mut self, engine_message: EngineMessage) {
+ if self.is_unordered(&engine_message) {
+ self.unordered.add(engine_message).unwrap();
+ } else if let Synced(TimeWrap, timestamp) = engine_message {
+ self.ordered
+ .add(Synced(TimeWrap, timestamp + self.hi_ticks))
+ .unwrap();
+ self.hi_ticks += 65536;
+ } else if let Synced(message, timestamp) = engine_message {
+ self.ordered
+ .add(Synced(message, timestamp + self.hi_ticks))
+ .unwrap();
+ } else {
+ self.ordered.add(engine_message).unwrap();
+ }
+ }
+
+ pub fn pop(&mut self, timestamp: u32) -> Option<EngineMessage> {
+ if let Ok(message) = self.unordered.remove() {
+ Some(message)
+ } else if let Ok(Synced(_, message_timestamp)) = self.ordered.peek() {
+ if message_timestamp == timestamp {
+ self.ordered.remove().ok()
+ } else {
+ None
+ }
+ } else {
+ self.ordered.remove().ok()
+ }
+ }
+
+ pub fn iter(&mut self, timestamp: u32) -> MessagesQueueIterator {
+ MessagesQueueIterator {
+ timestamp,
+ queue: self,
+ }
+ }
+}
+
+pub struct MessagesQueueIterator<'a> {
+ timestamp: u32,
+ queue: &'a mut MessagesQueue,
+}
+
+impl<'a> Iterator for MessagesQueueIterator<'a> {
+ type Item = EngineMessage;
+
+ fn next(&mut self) -> Option<EngineMessage> {
+ self.queue.pop(self.timestamp)
+ }
+}
+
+#[test]
+fn queue_order() {
+ use crate::messages::UnorderedEngineMessage::*;
+
+ let mut queue = MessagesQueue::new(QueueChatStrategy::LocalGame);
+
+ queue.push(Synced(Skip, 1));
+ queue.push(Unsynced(ChatMessage("hi".to_string())));
+ queue.push(Synced(TimeWrap, 65535));
+ queue.push(Unordered(Ping));
+ queue.push(Synced(Skip, 2));
+
+ let zero_tick: Vec<EngineMessage> = queue.iter(0).collect();
+ assert_eq!(zero_tick, vec![Unordered(Ping)]);
+ assert_eq!(queue.pop(1), Some(Synced(Skip, 1)));
+ assert_eq!(queue.pop(1), Some(Unsynced(ChatMessage("hi".to_string()))));
+ assert_eq!(queue.pop(1), None);
+ assert_eq!(queue.pop(2), None);
+ assert_eq!(queue.pop(65535), Some(Synced(TimeWrap, 65535)));
+ assert_eq!(queue.pop(65535), None);
+ assert_eq!(queue.pop(65538), Some(Synced(Skip, 65538)));
+ assert_eq!(queue.pop(65538), None);
+ assert_eq!(queue.pop(65539), None);
+}