]> git.proxmox.com Git - rustc.git/blame - vendor/prodash/src/progress/log.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / vendor / prodash / src / progress / log.rs
CommitLineData
0a29b90c
FG
1use std::{
2 sync::{
3 atomic::{AtomicBool, Ordering},
4 Arc,
5 },
6 time::Duration,
7};
8
9use crate::{
10 messages::MessageLevel,
11 progress::{Id, Step, StepShared},
12 Progress, Unit,
13};
14
15/// A [`Progress`] implementation which displays progress as it happens without the use of a renderer.
16///
17/// Note that this incurs considerable performance cost as each progress calls ends up getting the system time
18/// to see if progress information should actually be emitted.
19pub struct Log {
20 name: String,
21 id: Id,
22 max: Option<usize>,
23 unit: Option<Unit>,
24 step: usize,
25 current_level: usize,
26 max_level: usize,
27 trigger: Arc<AtomicBool>,
28}
29
30const EMIT_LOG_EVERY_S: f32 = 0.5;
31const SEP: &str = "::";
32
33impl Log {
34 /// Create a new instance from `name` while displaying progress information only up to `max_level`.
35 pub fn new(name: impl Into<String>, max_level: Option<usize>) -> Self {
36 let trigger = Arc::new(AtomicBool::new(true));
37 std::thread::spawn({
38 let duration = Duration::from_secs_f32(EMIT_LOG_EVERY_S);
39 let trigger = Arc::downgrade(&trigger);
40 move || {
41 while let Some(t) = trigger.upgrade() {
42 t.store(true, Ordering::Relaxed);
43 std::thread::sleep(duration);
44 }
45 }
46 });
47 Log {
48 name: name.into(),
49 id: crate::progress::UNKNOWN,
50 current_level: 0,
51 max_level: max_level.unwrap_or(usize::MAX),
52 max: None,
53 step: 0,
54 unit: None,
55 trigger,
56 }
57 }
58}
59
60impl Progress for Log {
61 type SubProgress = Log;
62
63 fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
64 self.add_child_with_id(name, crate::progress::UNKNOWN)
65 }
66
67 fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
68 Log {
69 name: format!("{}{}{}", self.name, SEP, Into::<String>::into(name)),
70 id,
71 current_level: self.current_level + 1,
72 max_level: self.max_level,
73 step: 0,
74 max: None,
75 unit: None,
76 trigger: Arc::clone(&self.trigger),
77 }
78 }
79
80 fn init(&mut self, max: Option<usize>, unit: Option<Unit>) {
81 self.max = max;
82 self.unit = unit;
83 }
84
85 fn set(&mut self, step: usize) {
86 self.step = step;
87 if self.current_level > self.max_level {
88 return;
89 }
90 if self.trigger.swap(false, Ordering::Relaxed) {
91 match (self.max, &self.unit) {
92 (max, Some(unit)) => log::info!("{} → {}", self.name, unit.display(step, max, None)),
93 (Some(max), None) => log::info!("{} → {} / {}", self.name, step, max),
94 (None, None) => log::info!("{} → {}", self.name, step),
95 }
96 }
97 }
98
99 fn unit(&self) -> Option<Unit> {
100 self.unit.clone()
101 }
102
103 fn max(&self) -> Option<usize> {
104 self.max
105 }
106
107 fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
108 let prev = self.max;
109 self.max = max;
110 prev
111 }
112
113 fn step(&self) -> usize {
114 self.step
115 }
116
117 fn inc_by(&mut self, step: usize) {
118 self.set(self.step + step)
119 }
120
121 fn set_name(&mut self, name: impl Into<String>) {
122 let name = name.into();
123 self.name = self
124 .name
125 .split("::")
126 .next()
127 .map(|parent| format!("{}{}{}", parent.to_owned(), SEP, name))
128 .unwrap_or(name);
129 }
130
131 fn name(&self) -> Option<String> {
132 self.name.split(SEP).nth(1).map(ToOwned::to_owned)
133 }
134
135 fn id(&self) -> Id {
136 self.id
137 }
138
fe692bf9 139 fn message(&self, level: MessageLevel, message: impl Into<String>) {
0a29b90c
FG
140 let message: String = message.into();
141 match level {
142 MessageLevel::Info => log::info!("ℹ{} → {}", self.name, message),
143 MessageLevel::Failure => log::error!("𐄂{} → {}", self.name, message),
144 MessageLevel::Success => log::info!("✓{} → {}", self.name, message),
145 }
146 }
147
148 fn counter(&self) -> Option<StepShared> {
149 None
150 }
151}