summaryrefslogtreecommitdiffstats
path: root/vendor/prodash/src/messages.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/prodash/src/messages.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-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.rs126
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,
+}