@@ -0,0 +1,75 @@
1+use std::{collections::HashMap, time::SystemTime};
3+#[derive(Default, Debug)]
4+pub struct ProgressSpinners {
5+ inner: HashMap<usize, Spinner>,
8+impl ProgressSpinners {
9+ pub fn get(&self, id: usize) -> Option<&Spinner> {
13+ pub fn get_or_create(&mut self, id: usize) -> &mut Spinner {
14+ self.inner.entry(id).or_insert_with(Spinner::default)
18+impl Default for Spinner {
19+ fn default() -> Self {
26+ frames: Vec<&'static str>,
28+ start: Option<SystemTime>,
33+ /// Creates a new spinner with `frames` and `interval`.
34+ /// Expects the frames count and interval to be greater than 0.
35+ pub fn new(frames: Vec<&'static str>, interval: u64) -> Self {
36+ let count = frames.len();
38+ assert!(interval > 0);
48+ pub fn dots(interval: u64) -> Self {
49+ Self::new(vec!["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"], interval)
52+ pub fn start(&mut self) {
53+ self.start = Some(SystemTime::now());
56+ pub fn frame(&self) -> Option<&str> {
59+ .map(|time| SystemTime::now().duration_since(time))?
62+ / self.interval as u128) as usize
65+ self.frames.get(idx).copied()
68+ pub fn stop(&mut self) {
72+ pub fn is_stopped(&self) -> bool {