diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/prodash/src/messages.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/prodash/src/messages.rs')
-rw-r--r-- | vendor/prodash/src/messages.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/vendor/prodash/src/messages.rs b/vendor/prodash/src/messages.rs new file mode 100644 index 000000000..2abd63830 --- /dev/null +++ b/vendor/prodash/src/messages.rs @@ -0,0 +1,126 @@ +use std::time::SystemTime; + +/// The severity of a message +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub enum MessageLevel { + /// Rarely sent information related to the progress, not to be confused with the progress itself + Info, + /// Used to indicate that a task has failed, along with the reason + Failure, + /// Indicates a task was completed successfully + Success, +} + +/// A message to be stored along with the progress tree. +/// +/// It is created by [`Tree::message(…)`](./struct.Item.html#method.message). +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Message { + /// The time at which the message was sent. + pub time: SystemTime, + /// The severity of the message + pub level: MessageLevel, + /// The name of the task that created the `Message` + pub origin: String, + /// The message itself + pub message: String, +} + +/// A ring buffer for messages. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct MessageRingBuffer { + pub(crate) buf: Vec<Message>, + cursor: usize, + total: usize, +} + +impl MessageRingBuffer { + /// Create a new instance the ability to hold `capacity` amount of messages. + pub fn with_capacity(capacity: usize) -> MessageRingBuffer { + MessageRingBuffer { + buf: Vec::with_capacity(capacity), + cursor: 0, + total: 0, + } + } + + /// Push a `message` from `origin` at severity `level` into the buffer, possibly overwriting the last message added. + pub fn push_overwrite(&mut self, level: MessageLevel, origin: String, message: impl Into<String>) { + let msg = Message { + time: SystemTime::now(), + level, + origin, + message: message.into(), + }; + if self.has_capacity() { + self.buf.push(msg) + } else { + self.buf[self.cursor] = msg; + self.cursor = (self.cursor + 1) % self.buf.len(); + } + self.total = self.total.wrapping_add(1); + } + + /// Copy all messages currently contained in the buffer to `out`. + pub fn copy_all(&self, out: &mut Vec<Message>) { + out.clear(); + if self.buf.is_empty() { + return; + } + out.extend_from_slice(&self.buf[self.cursor % self.buf.len()..]); + if self.cursor != self.buf.len() { + out.extend_from_slice(&self.buf[..self.cursor]); + } + } + + /// Copy all new messages into `out` that where received since the last time this method was called provided + /// its `previous` return value. + pub fn copy_new(&self, out: &mut Vec<Message>, previous: Option<MessageCopyState>) -> MessageCopyState { + out.clear(); + match previous { + Some(MessageCopyState { cursor, buf_len, total }) => { + if self.total.saturating_sub(total) >= self.buf.capacity() { + self.copy_all(out); + } else { + let new_elements_below_cap = self.buf.len().saturating_sub(buf_len); + let cursor_ofs: isize = self.cursor as isize - cursor as isize; + match cursor_ofs { + // there was some capacity left without wrapping around + c if c == 0 => { + out.extend_from_slice(&self.buf[self.buf.len() - new_elements_below_cap..]); + } + // cursor advanced + c if c > 0 => { + out.extend_from_slice(&self.buf[(cursor % self.buf.len())..self.cursor]); + } + // cursor wrapped around + c if c < 0 => { + out.extend_from_slice(&self.buf[(cursor % self.buf.len())..]); + out.extend_from_slice(&self.buf[..self.cursor]); + } + _ => unreachable!("logic dictates that… yeah, you really shouldn't ever see this!"), + } + } + } + None => self.copy_all(out), + }; + MessageCopyState { + cursor: self.cursor, + buf_len: self.buf.len(), + total: self.total, + } + } + + fn has_capacity(&self) -> bool { + self.buf.len() < self.buf.capacity() + } +} + +/// State used to keep track of what's new since the last time message were copied. +/// +/// Note that due to the nature of a ring buffer, there is no guarantee that you see all messages. +pub struct MessageCopyState { + cursor: usize, + buf_len: usize, + total: usize, +} |