Created
September 9, 2023 05:15
-
-
Save mihai-craita/ca38a199d422050ac45d66b9f67dbaf2 to your computer and use it in GitHub Desktop.
The final state of the code from this great talk "Type-Driven API Design in Rust" by Will Crichton: https://www.youtube.com/watch?v=bnnacleqg6k
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{time::Duration, iter::Iterator, thread::sleep}; | |
const CLEAR: &str = "\x1B[2J\x1B[1;1H"; | |
struct Unbounded; | |
struct Bounded { | |
bound: usize, | |
delims: (char, char) | |
} | |
struct Progress<Iter, Bound> { | |
iter: Iter, | |
i: usize, | |
bound: Bound | |
} | |
trait ProgressDisplay: Sized { | |
fn display<Iter>(&self, progress: &Progress<Iter, Self>); | |
} | |
impl ProgressDisplay for Unbounded { | |
fn display<Iter>(&self, progress: &Progress<Iter, Self>) { | |
println!("{}", "*".repeat(progress.i)); | |
} | |
} | |
impl ProgressDisplay for Bounded { | |
fn display<Iter>(&self, progress: &Progress<Iter, Self>) { | |
println!("{}{}{}{}", self.delims.0, "*".repeat(progress.i), " ".repeat(self.bound - progress.i), self.delims.1); | |
} | |
} | |
impl<Iter> Progress<Iter, Unbounded> { | |
pub fn new(iter: Iter) -> Self { | |
Progress{iter, i: 0, bound: Unbounded} | |
} | |
} | |
impl<Iter> Progress<Iter, Unbounded> | |
where Iter: ExactSizeIterator { | |
pub fn with_bound(self) -> Progress<Iter, Bounded> { | |
let bound = Bounded { | |
bound: self.iter.len(), | |
delims: ('[', ']') | |
}; | |
Progress { iter: self.iter, i: self.i, bound } | |
} | |
} | |
impl<Iter> Progress<Iter, Bounded> { | |
pub fn with_delims(mut self, delims: (char, char)) -> Self { | |
self.bound.delims = delims; | |
self | |
} | |
} | |
impl<Iter, B> Iterator for Progress<Iter, B> | |
where Iter: Iterator, B: ProgressDisplay { | |
type Item = Iter::Item; | |
fn next(&mut self) -> Option<Self::Item> { | |
print!("{}", CLEAR); | |
self.bound.display(self); | |
self.i += 1; | |
self.iter.next() | |
} | |
} | |
trait ProgressIteratorExt: Sized { | |
fn progress(self) -> Progress<Self, Unbounded>; | |
} | |
impl<Iter> ProgressIteratorExt for Iter | |
{ | |
fn progress(self) -> Progress<Self, Unbounded> { | |
Progress::new(self) | |
} | |
} | |
fn expensive_calculation(_n: &i32) { | |
sleep(Duration::from_secs(1)); | |
} | |
fn main() { | |
let brkts = ('<', '>'); | |
// for n in (0 .. ).progress().with_delims(brkts) { | |
// expensive_calculation(&n); | |
// } | |
let v: Vec<i32> = vec![1, 2, 3]; | |
for n in v.iter().progress().with_bound().with_delims(brkts) { | |
expensive_calculation(n); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment