use std::borrow::Cow;
use std::sync::Arc;

fn fizz_buzz(i: i32) -> Cow<'static, str> {
    if i % 15 == 0 {
        "FizzBuzz".into()
    } else if i % 5 == 0 {
        "Buzz".into()
    } else if i % 3 == 0 {
        "Fizz".into()
    } else {
        i.to_string().into()
    }
}
/*
struct WithCtx<'a,T,U>  where U: 'a {ctx: T, val: &'a U}

impl<'a,T,U> Deref for WithCtx<'a,T,U> {
  type Target = U;
  fn deref(&self) -> &Self::Target {self.val}
}*/

fn print_pointer<T>(x : *const T) {println!("{:?}",x);}



fn main() {
    {
      let x = 4;
      let ref y = 5;
      let xp : *const _ = &x;
      let yp : *const _ = y;
      let ypp : *const _ = &y;
      println!("{:?}, {:?}, {:?}", xp, yp, ypp);
      print_pointer(&xp);
    }
    {
        //let x;
        let y : Vec<_> = (0..).filter(|x| x%2==0).take(20).collect();
        {
            //let xs = vec![vec![2]];
            //x = WithCtx{ctx: xs, val: &xs[0]};
            //x = &xs[0];
        }

        println!("{:?}", y);
    }

    {
        let mut cow0 = Arc::new(75);
        let cow1 = cow0.clone();

        // *(&mut cow0).make_mut() += 1;
        *Arc::make_mut(&mut cow0) += 1;

        println!("{}", cow1);
    }

    for i in 1..101 {
        let mut x = fizz_buzz(i);
        let y = x.clone();
        x.to_mut().push('!');
        println!("{}", x.to_string());
        println!("{}", y);
    }

    let map = [(3, "Fizz"), (5, "Buzz"), (7, "Wazz")];

    for i in 1..111 {
        let mut result = String::new();

        for &(n, str) in &map {
            if i % n == 0 {
                result.push_str(str);
            }
        }
        if result.is_empty() {
            result = i.to_string();
        };
        println!("{}", result);
    }
}