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.
@@ -43,7 +46,7 @@ impl ProgressBar {
4346 /// progress_bar.finish().unwrap(); // clean up and write a line break (move to next line)
4447 /// // stdout lock is released when `progress_bar` goes out of scope
4548 /// ```
46- pub fn new ( total : Option < u64 > , prompt : & str ) -> Self {
49+ pub fn new ( total : Option < NonZero < u64 > > , prompt : & str ) -> Self {
4750 let stdout_handle = stdout ( ) . lock ( ) ;
4851 let is_interactive = stdout_handle. is_terminal ( ) ;
4952 Self {
@@ -61,7 +64,7 @@ impl ProgressBar {
6164 /// If the `total` is known, then the progress bar will be updated based on the percentage of `current` to `total`.
6265 /// If the `total` is unknown, then the progress bar will simply increment by one step for each call to this method.
6366 pub fn inc ( & mut self , delta : u64 ) -> Result < ( ) > {
64- self . current += delta;
67+ self . current = self . current . saturating_add ( delta) ;
6568 self . render ( )
6669 }
6770
@@ -77,7 +80,8 @@ impl ProgressBar {
7780 /// Subsequent updates should be made using [`Self::inc()`], which will call this method internally.
7881 pub fn render ( & mut self ) -> Result < ( ) > {
7982 let advance_bar = self . total . map ( |total| {
80- let progress = self . current as f64 / total as f64 ;
83+ let total = total. get ( ) ;
84+ let progress = self . current . min ( total) as f64 / total as f64 ;
8185
8286 ( progress * Self :: MAX_BAR_WIDTH as f64 ) . floor ( ) as u32
8387 } ) ;
@@ -142,6 +146,8 @@ impl ProgressBar {
142146
143147#[ cfg( test) ]
144148mod tests {
149+ use std:: num:: NonZero ;
150+
145151 use super :: ProgressBar ;
146152
147153 #[ test]
@@ -155,7 +161,7 @@ mod tests {
155161
156162 #[ test]
157163 fn with_total ( ) {
158- let mut progress_bar = ProgressBar :: new ( Some ( 100 ) , "Processing" ) ;
164+ let mut progress_bar = ProgressBar :: new ( Some ( NonZero :: new ( 100 ) . unwrap ( ) ) , "Processing" ) ;
159165 for _ in 0 ..100 {
160166 progress_bar. inc ( 1 ) . unwrap ( ) ;
161167 }
0 commit comments