async-rust 0.1.1

async rust examples
/*
 * Author: 邹航标 (No. 43)
 *
 * Useful links:
 *
 * https://github.com/AmadeusGB/SubstrateClass/blob/master/lesson5/area/src/main.rs
 * https://shimo.im/docs/rTJPC8PTpD3xJGVY/read
 * https://wj.qq.com/s2/7525430/1f79/
 * https://play.rust-lang.org/
 */

// solution 1
#[derive(Debug)]
enum TrafficLight {
    Red,
    Green,
    Yellow,
}

trait Light {
    fn duration(&self) -> i32;
}

impl Light for TrafficLight {
    fn duration(&self) -> i32 {
        return match self {
            TrafficLight::Red => 30,
            TrafficLight::Green => 5,
            TrafficLight::Yellow => 45,
        };
    }
}

// https://doc.rust-lang.org/book/ch10-02-traits.html#specifying-multiple-trait-bounds-with-the--syntax
// fn display_light<T: Light + std::fmt::Debug>(l: T){
// fn display_light(l: impl Light + std::fmt::Debug){
fn _display_light<T>(light: T)
    where T: Light + std::fmt::Debug
{
    println!("{:?} light lasts for {}s", light, light.duration())
}

macro_rules! display_light {
    ($( $light:expr),* $(,)?) => {{
        $( println!("{:?} light lasts for {}s", $light, $light.duration()); )*
    }};
}

fn solution1() {
    display_light!(
        TrafficLight::Red,
        TrafficLight::Green,
        TrafficLight::Yellow,
    )
}

// solution 2
fn sum_u32(xs: &[u32]) -> Option<u32> {
    xs.iter().try_fold(0u32, |acc, &x| acc.checked_add(x))
}

fn _display_sum(array: &[u32]) {
    println!("Sum of {:?} = {:?}", array, sum_u32(array))
}

macro_rules! display_sum {
    ( $( $array:expr ),* $(,)? ) => {{
        $(
            let array : &[u32] = $array;
            println!("Sum of {:?} = {:?}", array, sum_u32(array));
        )*
    }};
}

fn solution2() {
    display_sum!(
        &[],
        &[0],
        &[1],
        &[1, 2, 3, 4],
        &[std::u32::MAX],
        &[std::u32::MAX, 0],
        &[std::u32::MAX, 1],
        &[std::u32::MAX, 1, 2, 3, 4],
    )
}

// solution 3
trait Shape {
    type Output;
    fn area(&self) -> Self::Output;
}

#[derive(Debug)]
struct Square<T>(T);

#[derive(Debug)]
struct Circle<T>(T);

#[derive(Debug)]
struct Triangle<T>(T, T);

#[derive(Debug)]
struct Rectangle<T>(T, T);

impl<T: std::ops::Mul<Output = T> + Copy> Shape for Square<T> {
    type Output = T;
    fn area(&self) -> Self::Output {
        self.0 * self.0
    }
}

impl<T: std::ops::Mul<Output = T> + Into<f64> + Copy> Shape for Circle<T> {
    type Output = f64;
    fn area(&self) -> Self::Output {
        (self.0 * self.0).into() * std::f64::consts::PI
    }
}

impl<T: std::ops::Mul<Output = T> + Copy> Shape for Rectangle<T> {
    type Output = T;
    fn area(&self) -> Self::Output {
        self.0 * self.1
    }
}

impl<T: std::ops::Mul<Output = T> + Into<f64> + Copy> Shape for Triangle<T> {
    type Output = f64;
    fn area(&self) -> Self::Output {
        (self.0 * self.1).into() * 0.5
    }
}

/*
fn display_shape(s: (impl Shape + std::fmt::Debug)){
    println!("{:?}'s area is {}", s, s.area())
}
*/

// https://stackoverflow.com/questions/43143327/how-to-allow-optional-trailing-commas-in-macros
macro_rules! display_shape {
    ($( $shape:expr),* $(,)?) => {{
        $( println!("Area of {:?} = {}", $shape, $shape.area()); )*
    }};
}

fn solution3() {
    display_shape!(
        Square(1),
        Square(0.2),
        Circle(1),
        Rectangle(1, 2),
        Rectangle(0.1, 0.2),
        Triangle(1, 2),
        Triangle(0.1, 0.2),
    )
}

fn main() {
    println!("\n# solution 1");
    solution1();
    println!("\n# solution 2");
    solution2();
    println!("\n# solution 3");
    solution3();
}

// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=363dea3ab64375f51511cf8a60f165c4