1- use std:: io:: { IsTerminal , Result , Write , stdout} ;
1+ use std:: {
2+ io:: { IsTerminal , Result , Write , stdout} ,
3+ num:: NonZero ,
4+ } ;
25
36/// A simple progress bar implementation that supports both interactive and non-interactive terminals.
47pub struct ProgressBar {
58 /// The `total` size of the task being tracked, if known.
6- total : Option < u64 > ,
9+ total : Option < NonZero < u64 > > ,
710 /// The `current` progress towards the `total`.
811 current : u64 ,
912 /// The number of `steps` completed in the progress bar.
@@ -34,16 +37,20 @@ impl ProgressBar {
3437 /// Creates a new `ProgressBar` instance.
3538 ///
3639 /// This is considered infallible, but it is recommended to call [`Self::render()`] immediately after instantiation.
40+ ///
3741 /// ```
42+ /// use std::num::NonZero;
3843 /// use clang_installer::ProgressBar;
39- /// let mut progress_bar = ProgressBar::new(Some(100), "Downloading");
44+ ///
45+ /// let total = NonZero::new(100);
46+ /// let mut progress_bar = ProgressBar::new(total, "Downloading");
4047 /// progress_bar.render().unwrap(); // render 0% state
4148 /// progress_bar.inc(50).unwrap(); // render 50% state
4249 /// progress_bar.inc(50).unwrap(); // render 100% state
4350 /// progress_bar.finish().unwrap(); // clean up and write a line break (move to next line)
4451 /// // stdout lock is released when `progress_bar` goes out of scope
4552 /// ```
46- pub fn new ( total : Option < u64 > , prompt : & str ) -> Self {
53+ pub fn new ( total : Option < NonZero < u64 > > , prompt : & str ) -> Self {
4754 let stdout_handle = stdout ( ) . lock ( ) ;
4855 let is_interactive = stdout_handle. is_terminal ( ) ;
4956 Self {
@@ -61,7 +68,7 @@ impl ProgressBar {
6168 /// If the `total` is known, then the progress bar will be updated based on the percentage of `current` to `total`.
6269 /// If the `total` is unknown, then the progress bar will simply increment by one step for each call to this method.
6370 pub fn inc ( & mut self , delta : u64 ) -> Result < ( ) > {
64- self . current += delta;
71+ self . current = self . current . saturating_add ( delta) ;
6572 self . render ( )
6673 }
6774
@@ -77,7 +84,8 @@ impl ProgressBar {
7784 /// Subsequent updates should be made using [`Self::inc()`], which will call this method internally.
7885 pub fn render ( & mut self ) -> Result < ( ) > {
7986 let advance_bar = self . total . map ( |total| {
80- let progress = self . current as f64 / total as f64 ;
87+ let total = total. get ( ) ;
88+ let progress = self . current . min ( total) as f64 / total as f64 ;
8189
8290 ( progress * Self :: MAX_BAR_WIDTH as f64 ) . floor ( ) as u32
8391 } ) ;
@@ -142,6 +150,8 @@ impl ProgressBar {
142150
143151#[ cfg( test) ]
144152mod tests {
153+ use std:: num:: NonZero ;
154+
145155 use super :: ProgressBar ;
146156
147157 #[ test]
@@ -155,7 +165,7 @@ mod tests {
155165
156166 #[ test]
157167 fn with_total ( ) {
158- let mut progress_bar = ProgressBar :: new ( Some ( 100 ) , "Processing" ) ;
168+ let mut progress_bar = ProgressBar :: new ( Some ( NonZero :: new ( 100 ) . unwrap ( ) ) , "Processing" ) ;
159169 for _ in 0 ..100 {
160170 progress_bar. inc ( 1 ) . unwrap ( ) ;
161171 }
0 commit comments