Skip to content

Instantly share code, notes, and snippets.

@mihai-craita
Created September 9, 2023 05:15
Show Gist options
  • Save mihai-craita/ca38a199d422050ac45d66b9f67dbaf2 to your computer and use it in GitHub Desktop.
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
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