typetui 0.2.1

A terminal-based typing test.
Documentation
trait Summary {
    fn summarize(&self) -> String;
    
    fn summarize_author(&self) -> String;
    
    fn default_summary(&self) -> String {
        format!("(Read more from {}...)", self.summarize_author())
    }
}

struct NewsArticle {
    headline: String,
    location: String,
    author: String,
    content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
    
    fn summarize_author(&self) -> String {
        self.author.clone()
    }
}

struct Tweet {
    username: String,
    content: String,
    reply: bool,
    retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
    
    fn summarize_author(&self) -> String {
        self.username.clone()
    }
}

fn notify<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    
    largest
}

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

struct Container<T, U> {
    first: T,
    second: U,
}

impl<T, U> Container<T, U> {
    fn new(first: T, second: U) -> Self {
        Self { first, second }
    }
    
    fn mix<V, W>(self, other: Container<V, W>) -> Container<T, W> {
        Container {
            first: self.first,
            second: other.second,
        }
    }
}

trait Drawable {
    fn draw(&self);
}

struct Circle {
    radius: f64,
}

impl Drawable for Circle {
    fn draw(&self) {
        println!("Drawing circle with radius {}", self.radius);
    }
}

struct Rectangle {
    width: f64,
    height: f64,
}

impl Drawable for Rectangle {
    fn draw(&self) {
        println!("Drawing rectangle {}x{}", self.width, self.height);
    }
}

fn draw_shapes(shapes: &Vec<Box<dyn Drawable>>) {
    for shape in shapes {
        shape.draw();
    }
}

trait Iterator {
    type Item;
    
    fn next(&mut self) -> Option<Self::Item>;
}

struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;
    
    fn next(&mut self) -> Option<Self::Item> {
        if self.count < 5 {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

fn blanket_impls() {
    trait ToString {
        fn to_string(&self) -> String;
    }
    
    impl<T: std::fmt::Display> ToString for T {
        fn to_string(&self) -> String {
            format!("{}", self)
        }
    }
    
    let s = 3.to_string();
    println!("{}", s);
}

fn trait_bounds() {
    fn print_debug<T: std::fmt::Debug>(item: T) {
        println!("{:?}", item);
    }
    
    fn compare<T: PartialOrd>(a: T, b: T) -> bool {
        a > b
    }
    
    print_debug(vec![1, 2, 3]);
    println!("5 > 3: {}", compare(5, 3));
}

fn multiple_trait_bounds() {
    fn process<T: std::fmt::Display + Clone>(item: T) {
        let cloned = item.clone();
        println!("{}", cloned);
    }
    
    process(String::from("hello"));
}

fn where_clauses<T, U>(t: &T, u: &U) -> i32
where
    T: std::fmt::Display + Clone,
    U: Clone + std::fmt::Debug,
{
    42
}

fn main() {
    let article = NewsArticle {
        headline: String::from("Penguins win the Stanley Cup Championship!"),
        location: String::from("Pittsburgh, PA, USA"),
        author: String::from("Iceburgh"),
        content: String::from("..."),
    };
    
    notify(&article);
    
    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    
    notify(&tweet);
    
    let numbers = vec![34, 50, 25, 100, 65];
    println!("Largest: {}", largest(&numbers));
    
    let float_point = Point { x: 3.0, y: 4.0 };
    println!("Distance: {}", float_point.distance_from_origin());
    
    let shapes: Vec<Box<dyn Drawable>> = vec![
        Box::new(Circle { radius: 5.0 }),
        Box::new(Rectangle { width: 10.0, height: 20.0 }),
    ];
    draw_shapes(&shapes);
    
    let mut counter = Counter::new();
    while let Some(i) = counter.next() {
        println!("Counter: {}", i);
    }
    
    blanket_impls();
    trait_bounds();
    multiple_trait_bounds();
}