<commit_before>use std::fmt::{Display, Error, Formatter};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Ge,
    Gt,
    Eql,       // ==
    EqlStrict, // ===
    Le,
    Lt,
    Minus,
    Neq,       // !=
    NeqStrict, // !==
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 70,
    Add = 60,
    Equality = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Ge | BinOp::Gt | BinOp::Eql | BinOp::Le | BinOp::Lt |
                BinOp::Neq | BinOp::EqlStrict | BinOp::NeqStrict
                => Precedence::Equality,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Ge => write!(fmt, ">="),
            BinOp::Gt => write!(fmt, ">"),
            BinOp::Eql => write!(fmt, "=="),
            BinOp::EqlStrict => write!(fmt, "==="),
            BinOp::Le => write!(fmt, "<="),
            BinOp::Lt => write!(fmt, "<"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Neq => write!(fmt, "!="),
            BinOp::NeqStrict => write!(fmt, "!=="),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Call(Box<Exp>, Vec<Box<Exp>>),
    Defun(Option<String>, Vec<String>, Vec<Stmt>),
    Float(f64),
    InstanceVar(Box<Exp>, String),
    Neg(Box<Exp>),
    Null,
    NewObject(Box<Exp>, Vec<Box<Exp>>),
    Object(Vec<(String, Box<Exp>)>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    TypeOf(Box<Exp>),
    Str(String),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
            _ => Precedence::Const
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Exp {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Call(ref func, ref args) => {
                try!(write!(fmt, "{}(", func));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg));
                }

                write!(fmt, ")")
            }
            Exp::Defun(ref opt, ref params, ref body) => {
                try!(write!(fmt, "function"));

                if let &Some(ref func) = opt {
                    try!(write!(fmt, " {}", func));
                }

                try!(write!(fmt, "("));

                for (i, param) in params.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", param));
                }

                try!(write!(fmt, ") {{\n"));
                stmt_block!(body);

                let indent : String = (0..indent_level).map(|_| " ").collect();

                write!(fmt, "{}}}", indent)
            }
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::InstanceVar(ref obj, ref name) => write!(fmt, "{}.{}", obj, name),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::NewObject(ref name, ref args) => {
                try!(write!(fmt, "new {}(", name));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg))
                }

                write!(fmt, ")")
            }
            Exp::Null => write!(fmt, "null"),
            Exp::Object(ref properties) => {
                if properties.is_empty() {
                    return write!(fmt, "{{}}");
                }

                try!(writeln!(fmt, "{{"));

                let indent : String = (0..indent_level + 2).map(|_| " ").collect();

                for (i, &(ref name, ref prop)) in properties.iter().enumerate() {
                    if i != 0 {
                        try!(writeln!(fmt, ","));
                    }

                    try!(write!(fmt, "{}{}: ", indent, name));
                    try!(prop.fmt_helper(&mut fmt, indent_level + 2));
                }

                write!(fmt, "\n}}")
            }
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::TypeOf(ref e) => write!(fmt, "typeof {}", e),
            Exp::Str(ref s) => write!(fmt, "\"{}\"", s),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

impl Display for Exp {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}

#[derive(Clone, Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    Empty,
    If(Exp, Vec<Stmt>, Vec<Stmt>),
    Ret(Exp),
    Seq(Box<Stmt>, Box<Stmt>),
    Try(Vec<Stmt>, Vec<Stmt>, String, Vec<Stmt>), // try block, catch block, catch variable, finally block
    Throw(Box<Exp>),
    While(Exp, Vec<Stmt>),
}

impl Stmt {
    pub fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        macro_rules! indented_stmt {
            ($s:expr) => {
                try!($s.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        macro_rules! exp_semi {
            ($exp:expr) => {{
                try!($exp.fmt_helper(&mut fmt, indent_level));
                writeln!(fmt, ";")
            }}
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => {
                try!(write!(fmt, "{}{} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::BareExp(ref exp) => {
                try!(write!(fmt, "{}", indent));
                exp_semi!(exp)
            }
            Stmt::Decl(ref v, ref exp) => {
                try!(write!(fmt, "{}var {} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::Empty => Ok(()),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if (", indent));
                try!(e.fmt_helper(&mut fmt, indent_level + 2));
                try!(writeln!(fmt, ") {{\n"));
                stmt_block!(s);

                if els.len() > 0 {
                    stmt_block!(s);
                }

                //if let &Some(ref stmt) = els {
                //    try!(write!(fmt, "{}else {{\n", indent));
                //    indented_stmt!(stmt);
                //    try!(write!(fmt, "{}}}\n", indent));
                //}

                Ok(())
            }
            Stmt::Ret(ref e) => {
                try!(write!(fmt, "{}return ", indent));
                exp_semi!(e)
            }
            Stmt::Seq(ref s1, ref s2) => {
                try!(s1.fmt_helper(&mut fmt, indent_level));
                s2.fmt_helper(&mut fmt, indent_level)
            }
            Stmt::Throw(ref e) => {
                write!(fmt, "{}throw {}", indent, e)
            }
            Stmt::Try(ref stmt, ref catch_block, ref finally_block) => {
                try!(write!(fmt, "{}try {{\n", indent));
                stmt_block!(stmt);
                try!(write!(fmt, "{}}}\n", indent));

                if catch_block.len() > 0 {
                    try!(write!(fmt, "{}catch {{\n", indent));
                    stmt_block!(catch_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                if finally_block.len() > 0 {
                    try!(write!(fmt, "{}finally {{\n", indent));
                    stmt_block!(finally_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                stmt_block!(stmt);
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<commit_msg>...finish adding try/catch binding<commit_after>use std::fmt::{Display, Error, Formatter};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Ge,
    Gt,
    Eql,       // ==
    EqlStrict, // ===
    Le,
    Lt,
    Minus,
    Neq,       // !=
    NeqStrict, // !==
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 70,
    Add = 60,
    Equality = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Ge | BinOp::Gt | BinOp::Eql | BinOp::Le | BinOp::Lt |
                BinOp::Neq | BinOp::EqlStrict | BinOp::NeqStrict
                => Precedence::Equality,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Ge => write!(fmt, ">="),
            BinOp::Gt => write!(fmt, ">"),
            BinOp::Eql => write!(fmt, "=="),
            BinOp::EqlStrict => write!(fmt, "==="),
            BinOp::Le => write!(fmt, "<="),
            BinOp::Lt => write!(fmt, "<"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Neq => write!(fmt, "!="),
            BinOp::NeqStrict => write!(fmt, "!=="),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Call(Box<Exp>, Vec<Box<Exp>>),
    Defun(Option<String>, Vec<String>, Vec<Stmt>),
    Float(f64),
    InstanceVar(Box<Exp>, String),
    Neg(Box<Exp>),
    Null,
    NewObject(Box<Exp>, Vec<Box<Exp>>),
    Object(Vec<(String, Box<Exp>)>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    TypeOf(Box<Exp>),
    Str(String),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
            _ => Precedence::Const
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Exp {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Call(ref func, ref args) => {
                try!(write!(fmt, "{}(", func));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg));
                }

                write!(fmt, ")")
            }
            Exp::Defun(ref opt, ref params, ref body) => {
                try!(write!(fmt, "function"));

                if let &Some(ref func) = opt {
                    try!(write!(fmt, " {}", func));
                }

                try!(write!(fmt, "("));

                for (i, param) in params.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", param));
                }

                try!(write!(fmt, ") {{\n"));
                stmt_block!(body);

                let indent : String = (0..indent_level).map(|_| " ").collect();

                write!(fmt, "{}}}", indent)
            }
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::InstanceVar(ref obj, ref name) => write!(fmt, "{}.{}", obj, name),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::NewObject(ref name, ref args) => {
                try!(write!(fmt, "new {}(", name));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg))
                }

                write!(fmt, ")")
            }
            Exp::Null => write!(fmt, "null"),
            Exp::Object(ref properties) => {
                if properties.is_empty() {
                    return write!(fmt, "{{}}");
                }

                try!(writeln!(fmt, "{{"));

                let indent : String = (0..indent_level + 2).map(|_| " ").collect();

                for (i, &(ref name, ref prop)) in properties.iter().enumerate() {
                    if i != 0 {
                        try!(writeln!(fmt, ","));
                    }

                    try!(write!(fmt, "{}{}: ", indent, name));
                    try!(prop.fmt_helper(&mut fmt, indent_level + 2));
                }

                write!(fmt, "\n}}")
            }
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::TypeOf(ref e) => write!(fmt, "typeof {}", e),
            Exp::Str(ref s) => write!(fmt, "\"{}\"", s),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

impl Display for Exp {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}

#[derive(Clone, Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    Empty,
    If(Exp, Vec<Stmt>, Vec<Stmt>),
    Ret(Exp),
    Seq(Box<Stmt>, Box<Stmt>),
    // try block, catch variable, catch block, finally block
    Try(Vec<Stmt>, String, Vec<Stmt>, Vec<Stmt>),
    Throw(Box<Exp>),
    While(Exp, Vec<Stmt>),
}

impl Stmt {
    pub fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        macro_rules! indented_stmt {
            ($s:expr) => {
                try!($s.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        macro_rules! exp_semi {
            ($exp:expr) => {{
                try!($exp.fmt_helper(&mut fmt, indent_level));
                writeln!(fmt, ";")
            }}
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => {
                try!(write!(fmt, "{}{} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::BareExp(ref exp) => {
                try!(write!(fmt, "{}", indent));
                exp_semi!(exp)
            }
            Stmt::Decl(ref v, ref exp) => {
                try!(write!(fmt, "{}var {} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::Empty => Ok(()),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if (", indent));
                try!(e.fmt_helper(&mut fmt, indent_level + 2));
                try!(writeln!(fmt, ") {{\n"));
                stmt_block!(s);

                if els.len() > 0 {
                    stmt_block!(s);
                }

                //if let &Some(ref stmt) = els {
                //    try!(write!(fmt, "{}else {{\n", indent));
                //    indented_stmt!(stmt);
                //    try!(write!(fmt, "{}}}\n", indent));
                //}

                Ok(())
            }
            Stmt::Ret(ref e) => {
                try!(write!(fmt, "{}return ", indent));
                exp_semi!(e)
            }
            Stmt::Seq(ref s1, ref s2) => {
                try!(s1.fmt_helper(&mut fmt, indent_level));
                s2.fmt_helper(&mut fmt, indent_level)
            }
            Stmt::Throw(ref e) => {
                write!(fmt, "{}throw {}", indent, e)
            }
            Stmt::Try(ref stmt, ref catch_var, ref catch_block, ref finally_block) => {
                try!(write!(fmt, "{}try {{\n", indent));
                stmt_block!(stmt);
                try!(write!(fmt, "{}}}\n", indent));

                if catch_block.len() > 0 {
                    try!(write!(fmt, "{}catch ({}) {{\n", catch_var, indent));
                    stmt_block!(catch_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                if finally_block.len() > 0 {
                    try!(write!(fmt, "{}finally {{\n", indent));
                    stmt_block!(finally_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                stmt_block!(stmt);
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<|endoftext|>


<commit_before>/*extern crate hyper;
extern crate rustc_serialize;*/

//use std::io;
use std::io::Read;

use super::rustc_serialize::json;
use super::rustc_serialize::Decodable;

use super::hyper::Client;
use super::hyper::header::Connection;

static BASE_PATH: &'static str = "https://api.telegram.org/";

pub struct Bot {
    api_key: String
}

#[derive(RustcDecodable)]
struct GetMeResult {
    id: i32,
    first_name: String,
    username: String,
}

#[derive(RustcDecodable)]
pub struct GetMe {
    pub ok: bool,
    result: GetMeResult,
}

impl Bot {
    pub fn new(api_key: &str) -> Bot {
        Bot {
            api_key: api_key.to_string()
        }
    }

    pub fn get_me(&self) -> String {
        let path = format!("{}bot{}/getMe", BASE_PATH, self.api_key);
        let client = Client::new();
        let mut res = client.get(&path)
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        return body;
    }

    pub fn send_message(&self, chat_id: i32, text: String) -> String {
        let path = format!("{}bot{}/sendMessage?chat_id={}&text={}", BASE_PATH, self.api_key, chat_id, text);
        let client = Client::new();
        let mut res = client.get(&path)
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        return body;
    }
}
<commit_msg>make GetMeResult public<commit_after>/*extern crate hyper;
extern crate rustc_serialize;*/

//use std::io;
use std::io::Read;

use super::rustc_serialize::json;
use super::rustc_serialize::Decodable;

use super::hyper::Client;
use super::hyper::header::Connection;

static BASE_PATH: &'static str = "https://api.telegram.org/";

pub struct Bot {
    api_key: String
}

#[derive(RustcDecodable)]
pub struct GetMeResult {
    pub id: i32,
    pub first_name: String,
    pub username: String,
}

#[derive(RustcDecodable)]
pub struct GetMe {
    pub ok: bool,
    pub result: GetMeResult,
}

impl Bot {
    pub fn new(api_key: &str) -> Bot {
        Bot {
            api_key: api_key.to_string()
        }
    }

    pub fn get_me(&self) -> String {
        let path = format!("{}bot{}/getMe", BASE_PATH, self.api_key);
        let client = Client::new();
        let mut res = client.get(&path)
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        return body;
    }

    pub fn send_message(&self, chat_id: i32, text: String) -> String {
        let path = format!("{}bot{}/sendMessage?chat_id={}&text={}", BASE_PATH, self.api_key, chat_id, text);
        let client = Client::new();
        let mut res = client.get(&path)
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        return body;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[cfg(any(test, feature = "testing"))]
use crate::account_config::{account_resource_path, AccountResource};
use crate::{
    account_address::AccountAddress,
    account_config::get_account_resource_or_default,
    ledger_info::LedgerInfo,
    proof::{verify_account_state, AccountStateProof},
    transaction::Version,
};

use canonical_serialization::{SimpleDeserializer, SimpleSerializer};
use crypto::{
    hash::{AccountStateBlobHasher, CryptoHash, CryptoHasher},
    HashValue,
};
use failure::prelude::*;
#[cfg(any(test, feature = "testing"))]
use proptest::{arbitrary::Arbitrary, prelude::*};
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, convert::TryFrom, fmt};

#[derive(Clone, Eq, PartialEq, FromProto, IntoProto, Serialize, Deserialize)]
#[ProtoType(crate::proto::account_state_blob::AccountStateBlob)]
pub struct AccountStateBlob {
    blob: Vec<u8>,
}

impl fmt::Debug for AccountStateBlob {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let decoded = get_account_resource_or_default(&Some(self.clone()))
            .map(|resource| format!("{:#?}", resource))
            .unwrap_or_else(|_| String::from("[fail]"));

        write!(
            f,
            "AccountStateBlob {{ \n \
             Raw: 0x{} \n \
             Decoded: {} \n \
             }}",
            hex::encode(&self.blob),
            decoded,
        )
    }
}

impl AsRef<[u8]> for AccountStateBlob {
    fn as_ref(&self) -> &[u8] {
        &self.blob
    }
}

impl From<AccountStateBlob> for Vec<u8> {
    fn from(account_state_blob: AccountStateBlob) -> Vec<u8> {
        account_state_blob.blob
    }
}

impl From<Vec<u8>> for AccountStateBlob {
    fn from(blob: Vec<u8>) -> AccountStateBlob {
        AccountStateBlob { blob }
    }
}

impl TryFrom<&BTreeMap<Vec<u8>, Vec<u8>>> for AccountStateBlob {
    type Error = failure::Error;

    fn try_from(map: &BTreeMap<Vec<u8>, Vec<u8>>) -> Result<Self> {
        Ok(Self {
            blob: SimpleSerializer::serialize(map)?,
        })
    }
}

impl TryFrom<crate::proto::types::AccountStateBlob> for AccountStateBlob {
    type Error = Error;

    fn try_from(proto: crate::proto::types::AccountStateBlob) -> Result<Self> {
        Ok(proto.blob.into())
    }
}

impl From<AccountStateBlob> for crate::proto::types::AccountStateBlob {
    fn from(blob: AccountStateBlob) -> Self {
        Self { blob: blob.blob }
    }
}

#[cfg(any(test, feature = "testing"))]
impl From<AccountResource> for AccountStateBlob {
    fn from(account_resource: AccountResource) -> Self {
        let mut account_state: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        account_state.insert(
            account_resource_path(),
            SimpleSerializer::<Vec<u8>>::serialize(&account_resource).unwrap(),
        );
        AccountStateBlob::try_from(&account_state).unwrap()
    }
}

impl TryFrom<&AccountStateBlob> for BTreeMap<Vec<u8>, Vec<u8>> {
    type Error = failure::Error;

    fn try_from(account_state_blob: &AccountStateBlob) -> Result<Self> {
        SimpleDeserializer::deserialize(&account_state_blob.blob)
    }
}

impl CryptoHash for AccountStateBlob {
    type Hasher = AccountStateBlobHasher;

    fn hash(&self) -> HashValue {
        let mut hasher = Self::Hasher::default();
        hasher.write(&self.blob);
        hasher.finish()
    }
}

#[cfg(any(test, feature = "testing"))]
prop_compose! {
    pub fn account_state_blob_strategy()(account_resource in any::<AccountResource>()) -> AccountStateBlob {
        AccountStateBlob::from(account_resource)
    }
}

#[cfg(any(test, feature = "testing"))]
impl Arbitrary for AccountStateBlob {
    type Parameters = ();
    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
        account_state_blob_strategy().boxed()
    }

    type Strategy = BoxedStrategy<Self>;
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct AccountStateWithProof {
    /// The transaction version at which this account state is seen.
    pub version: Version,
    /// Blob value representing the account state. If this field is not set, it
    /// means the account does not exist.
    pub blob: Option<AccountStateBlob>,
    /// The proof the client can use to authenticate the value.
    pub proof: AccountStateProof,
}

impl AccountStateWithProof {
    /// Constructor.
    pub fn new(version: Version, blob: Option<AccountStateBlob>, proof: AccountStateProof) -> Self {
        Self {
            version,
            blob,
            proof,
        }
    }

    /// Verifies the the account state blob with the proof, both carried by `self`.
    ///
    /// Two things are ensured if no error is raised:
    ///   1. This account state exists in the ledger represented by `ledger_info`.
    ///   2. It belongs to account of `address` and is seen at the time the transaction at version
    /// `state_version` is just committed. To make sure this is the latest state, pass in
    /// `ledger_info.version()` as `state_version`.
    pub fn verify(
        &self,
        ledger_info: &LedgerInfo,
        version: Version,
        address: AccountAddress,
    ) -> Result<()> {
        ensure!(
            self.version == version,
            "State version ({}) is not expected ({}).",
            self.version,
            version,
        );

        verify_account_state(
            ledger_info,
            version,
            address.hash(),
            &self.blob,
            &self.proof,
        )
    }
}

impl FromProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(AccountStateWithProof {
            version: object.get_version(),
            blob: object
                .blob
                .take()
                .map(AccountStateBlob::from_proto)
                .transpose()?,
            proof: AccountStateProof::from_proto(object.take_proof())?,
        })
    }
}

impl IntoProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_version(self.version);
        if let Some(blob) = self.blob {
            out.set_blob(blob.into_proto());
        }
        out.set_proof(self.proof.into_proto());
        out
    }
}

#[cfg(test)]
mod account_state_blob_test;
<commit_msg>[types] impl conversions from/to prost proto and AccountStateWithProof<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[cfg(any(test, feature = "testing"))]
use crate::account_config::{account_resource_path, AccountResource};
use crate::{
    account_address::AccountAddress,
    account_config::get_account_resource_or_default,
    ledger_info::LedgerInfo,
    proof::{verify_account_state, AccountStateProof},
    transaction::Version,
};

use canonical_serialization::{SimpleDeserializer, SimpleSerializer};
use crypto::{
    hash::{AccountStateBlobHasher, CryptoHash, CryptoHasher},
    HashValue,
};
use failure::prelude::*;
#[cfg(any(test, feature = "testing"))]
use proptest::{arbitrary::Arbitrary, prelude::*};
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{
    collections::BTreeMap,
    convert::{TryFrom, TryInto},
    fmt,
};

#[derive(Clone, Eq, PartialEq, FromProto, IntoProto, Serialize, Deserialize)]
#[ProtoType(crate::proto::account_state_blob::AccountStateBlob)]
pub struct AccountStateBlob {
    blob: Vec<u8>,
}

impl fmt::Debug for AccountStateBlob {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let decoded = get_account_resource_or_default(&Some(self.clone()))
            .map(|resource| format!("{:#?}", resource))
            .unwrap_or_else(|_| String::from("[fail]"));

        write!(
            f,
            "AccountStateBlob {{ \n \
             Raw: 0x{} \n \
             Decoded: {} \n \
             }}",
            hex::encode(&self.blob),
            decoded,
        )
    }
}

impl AsRef<[u8]> for AccountStateBlob {
    fn as_ref(&self) -> &[u8] {
        &self.blob
    }
}

impl From<AccountStateBlob> for Vec<u8> {
    fn from(account_state_blob: AccountStateBlob) -> Vec<u8> {
        account_state_blob.blob
    }
}

impl From<Vec<u8>> for AccountStateBlob {
    fn from(blob: Vec<u8>) -> AccountStateBlob {
        AccountStateBlob { blob }
    }
}

impl TryFrom<&BTreeMap<Vec<u8>, Vec<u8>>> for AccountStateBlob {
    type Error = failure::Error;

    fn try_from(map: &BTreeMap<Vec<u8>, Vec<u8>>) -> Result<Self> {
        Ok(Self {
            blob: SimpleSerializer::serialize(map)?,
        })
    }
}

impl TryFrom<crate::proto::types::AccountStateBlob> for AccountStateBlob {
    type Error = Error;

    fn try_from(proto: crate::proto::types::AccountStateBlob) -> Result<Self> {
        Ok(proto.blob.into())
    }
}

impl From<AccountStateBlob> for crate::proto::types::AccountStateBlob {
    fn from(blob: AccountStateBlob) -> Self {
        Self { blob: blob.blob }
    }
}

#[cfg(any(test, feature = "testing"))]
impl From<AccountResource> for AccountStateBlob {
    fn from(account_resource: AccountResource) -> Self {
        let mut account_state: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        account_state.insert(
            account_resource_path(),
            SimpleSerializer::<Vec<u8>>::serialize(&account_resource).unwrap(),
        );
        AccountStateBlob::try_from(&account_state).unwrap()
    }
}

impl TryFrom<&AccountStateBlob> for BTreeMap<Vec<u8>, Vec<u8>> {
    type Error = failure::Error;

    fn try_from(account_state_blob: &AccountStateBlob) -> Result<Self> {
        SimpleDeserializer::deserialize(&account_state_blob.blob)
    }
}

impl CryptoHash for AccountStateBlob {
    type Hasher = AccountStateBlobHasher;

    fn hash(&self) -> HashValue {
        let mut hasher = Self::Hasher::default();
        hasher.write(&self.blob);
        hasher.finish()
    }
}

#[cfg(any(test, feature = "testing"))]
prop_compose! {
    pub fn account_state_blob_strategy()(account_resource in any::<AccountResource>()) -> AccountStateBlob {
        AccountStateBlob::from(account_resource)
    }
}

#[cfg(any(test, feature = "testing"))]
impl Arbitrary for AccountStateBlob {
    type Parameters = ();
    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
        account_state_blob_strategy().boxed()
    }

    type Strategy = BoxedStrategy<Self>;
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct AccountStateWithProof {
    /// The transaction version at which this account state is seen.
    pub version: Version,
    /// Blob value representing the account state. If this field is not set, it
    /// means the account does not exist.
    pub blob: Option<AccountStateBlob>,
    /// The proof the client can use to authenticate the value.
    pub proof: AccountStateProof,
}

impl AccountStateWithProof {
    /// Constructor.
    pub fn new(version: Version, blob: Option<AccountStateBlob>, proof: AccountStateProof) -> Self {
        Self {
            version,
            blob,
            proof,
        }
    }

    /// Verifies the the account state blob with the proof, both carried by `self`.
    ///
    /// Two things are ensured if no error is raised:
    ///   1. This account state exists in the ledger represented by `ledger_info`.
    ///   2. It belongs to account of `address` and is seen at the time the transaction at version
    /// `state_version` is just committed. To make sure this is the latest state, pass in
    /// `ledger_info.version()` as `state_version`.
    pub fn verify(
        &self,
        ledger_info: &LedgerInfo,
        version: Version,
        address: AccountAddress,
    ) -> Result<()> {
        ensure!(
            self.version == version,
            "State version ({}) is not expected ({}).",
            self.version,
            version,
        );

        verify_account_state(
            ledger_info,
            version,
            address.hash(),
            &self.blob,
            &self.proof,
        )
    }
}

impl FromProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(AccountStateWithProof {
            version: object.get_version(),
            blob: object
                .blob
                .take()
                .map(AccountStateBlob::from_proto)
                .transpose()?,
            proof: AccountStateProof::from_proto(object.take_proof())?,
        })
    }
}

impl IntoProto for AccountStateWithProof {
    type ProtoType = crate::proto::account_state_blob::AccountStateWithProof;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_version(self.version);
        if let Some(blob) = self.blob {
            out.set_blob(blob.into_proto());
        }
        out.set_proof(self.proof.into_proto());
        out
    }
}

impl TryFrom<crate::proto::types::AccountStateWithProof> for AccountStateWithProof {
    type Error = Error;

    fn try_from(mut proto: crate::proto::types::AccountStateWithProof) -> Result<Self> {
        Ok(Self::new(
            proto.version,
            proto
                .blob
                .take()
                .map(AccountStateBlob::try_from)
                .transpose()?,
            proto
                .proof
                .ok_or_else(|| format_err!("Missing proof"))?
                .try_into()?,
        ))
    }
}

impl From<AccountStateWithProof> for crate::proto::types::AccountStateWithProof {
    fn from(account: AccountStateWithProof) -> Self {
        Self {
            version: account.version,
            blob: account.blob.map(Into::into),
            proof: Some(account.proof.into()),
        }
    }
}

#[cfg(test)]
mod account_state_blob_test;
<|endoftext|>


<commit_before>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{self, moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone, Copy)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
/// An enum representing the PokemonSlot
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PokemonSlot {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
}
impl PokemonSlot {
    pub fn get_int(&self) -> usize {
        match *self {
            PokemonSlot::One => 1,
            PokemonSlot::Two => 2,
            PokemonSlot::Three => 3,
            PokemonSlot::Four => 4,
            PokemonSlot::Five => 5,
            PokemonSlot::Six => 6,
        }
    }
}
#[derive(Clone, Debug, PartialEq)]
pub enum Next {
    Switch(PokemonSlot),
    Move(moves::Technique),
    Flinch,
    None,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<Next>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<moves::Technique>,
    last_action: (Next, u8),
    switched: bool,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
            last_action: (Next::None, 0),
            switched: false,
        }
    }

    pub fn new_by_pokemon(pokemon: Vec<db::pokemon_token::PokemonToken>,
                          player_type: PlayerType)
                          -> Self {
        Player {
            player: player_type,
            pokemon_list: pokemon.clone(),
            pokemon_count: pokemon.len(),
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
        }
    }
    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        let mut alive = 0;
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].get_current().get_stat(&enums::Stats::Hp) == 0 {
                alive += 1;
            }
        }
        alive
    }
    /// Returns a Vec with the id´s in the player model from the pokemon which are alive
    pub fn get_alive_list(&mut self) -> Vec<usize> {
        let mut vec = Vec::new();
        for i in 0..self.pokemon_list.len() {
            if self.get_pokemon_list()[i].get_current().get_stat(&enums::Stats::Hp) != 0 {
                vec.push(i);
            }
        }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Checks if an attack is in the Attackslots and returns the Slot
    pub fn get_attack_slot(&mut self, attack: moves::Technique) -> Option<AttackSlot> {
        if self.get_attack(&AttackSlot::One) == attack {
            return Some(AttackSlot::One);
        } else if self.get_attack(&AttackSlot::Two) == attack {
            return Some(AttackSlot::Two);
        } else if self.get_attack(&AttackSlot::Three) == attack {
            return Some(AttackSlot::Three);
        } else if self.get_attack(&AttackSlot::Four) == attack {
            return Some(AttackSlot::Four);
        }
        None
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<Next> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<moves::Technique> {
        self.last_move.clone()
    }

    pub fn get_last_action(&self) -> &(Next, u8) {
        &self.last_action
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    pub fn get_switched(&mut self) -> bool {
        self.switched
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<Next>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        if !self.flags.contains_key(&flag) {
            self.flags.insert(flag, 0);
        } else {
            println!("It has no effect");
        }
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<moves::Technique>) {
        self.last_move = last;
    }

    /// Sets the last action
    pub fn set_last_action(&mut self, last: (Next, u8)) {
        self.last_action = last;
    }
    /// Sets the switched flag with a bool
    pub fn set_switched(&mut self, stat: bool) {
        self.switched = stat;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}
<commit_msg>Added new_by_pokemon() to techniques<commit_after>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{self, moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone, Copy)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
/// An enum representing the PokemonSlot
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PokemonSlot {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
}
impl PokemonSlot {
    pub fn get_int(&self) -> usize {
        match *self {
            PokemonSlot::One => 1,
            PokemonSlot::Two => 2,
            PokemonSlot::Three => 3,
            PokemonSlot::Four => 4,
            PokemonSlot::Five => 5,
            PokemonSlot::Six => 6,
        }
    }
}
#[derive(Clone, Debug, PartialEq)]
pub enum Next {
    Switch(PokemonSlot),
    Move(moves::Technique),
    Flinch,
    None,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<Next>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<moves::Technique>,
    last_action: (Next, u8),
    switched: bool,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
            last_action: (Next::None, 0),
            switched: false,
        }
    }

    pub fn new_by_pokemon(pokemon: Vec<db::pokemon_token::PokemonToken>,
                          player_type: PlayerType)
                          -> Self {
        Player {
            player: player_type,
            pokemon_list: pokemon.clone(),
            pokemon_count: pokemon.len(),
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
            last_action: (Next::None, 0),
            switched: false,
        }
    }
    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        let mut alive = 0;
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].get_current().get_stat(&enums::Stats::Hp) == 0 {
                alive += 1;
            }
        }
        alive
    }
    /// Returns a Vec with the id´s in the player model from the pokemon which are alive
    pub fn get_alive_list(&mut self) -> Vec<usize> {
        let mut vec = Vec::new();
        for i in 0..self.pokemon_list.len() {
            if self.get_pokemon_list()[i].get_current().get_stat(&enums::Stats::Hp) != 0 {
                vec.push(i);
            }
        }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Checks if an attack is in the Attackslots and returns the Slot
    pub fn get_attack_slot(&mut self, attack: moves::Technique) -> Option<AttackSlot> {
        if self.get_attack(&AttackSlot::One) == attack {
            return Some(AttackSlot::One);
        } else if self.get_attack(&AttackSlot::Two) == attack {
            return Some(AttackSlot::Two);
        } else if self.get_attack(&AttackSlot::Three) == attack {
            return Some(AttackSlot::Three);
        } else if self.get_attack(&AttackSlot::Four) == attack {
            return Some(AttackSlot::Four);
        }
        None
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<Next> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<moves::Technique> {
        self.last_move.clone()
    }

    pub fn get_last_action(&self) -> &(Next, u8) {
        &self.last_action
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    pub fn get_switched(&mut self) -> bool {
        self.switched
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<Next>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        if !self.flags.contains_key(&flag) {
            self.flags.insert(flag, 0);
        } else {
            println!("It has no effect");
        }
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<moves::Technique>) {
        self.last_move = last;
    }

    /// Sets the last action
    pub fn set_last_action(&mut self, last: (Next, u8)) {
        self.last_action = last;
    }
    /// Sets the switched flag with a bool
    pub fn set_switched(&mut self, stat: bool) {
        self.switched = stat;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::{is_type_diagnostic_item, match_def_path, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Local, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol};
use std::convert::TryInto;

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `push` immediately after creating a new `Vec`.
    ///
    /// **Why is this bad?** The `vec![]` macro is both more performant and easier to read than
    /// multiple `push` calls.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// let mut v: Vec<u32> = Vec::new();
    /// v.push(0);
    /// ```
    /// Use instead:
    /// ```rust
    /// let v: Vec<u32> = vec![0];
    /// ```
    pub VEC_INIT_THEN_PUSH,
    perf,
    "`push` immediately after `Vec` creation"
}

impl_lint_pass!(VecInitThenPush => [VEC_INIT_THEN_PUSH]);

#[derive(Default)]
pub struct VecInitThenPush {
    searcher: Option<VecPushSearcher>,
}

#[derive(Clone, Copy)]
enum VecInitKind {
    New,
    WithCapacity(u64),
}
struct VecPushSearcher {
    init: VecInitKind,
    name: Symbol,
    lhs_is_local: bool,
    lhs_span: Span,
    err_span: Span,
    found: u64,
}
impl VecPushSearcher {
    fn display_err(&self, cx: &LateContext<'_>) {
        match self.init {
            _ if self.found == 0 => return,
            VecInitKind::WithCapacity(x) if x > self.found => return,
            _ => (),
        };

        let mut s = if self.lhs_is_local {
            String::from("let ")
        } else {
            String::new()
        };
        s.push_str(&snippet(cx, self.lhs_span, ".."));
        s.push_str(" = vec![..];");

        span_lint_and_sugg(
            cx,
            VEC_INIT_THEN_PUSH,
            self.err_span,
            "calls to `push` immediately after creation",
            "consider using the `vec![]` macro",
            s,
            Applicability::HasPlaceholders,
        );
    }
}

impl LateLintPass<'_> for VecInitThenPush {
    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
        self.searcher = None;
        if_chain! {
            if !in_external_macro(cx.sess(), local.span);
            if let Some(init) = local.init;
            if let PatKind::Binding(BindingAnnotation::Mutable, _, ident, None) = local.pat.kind;
            if let Some(init_kind) = get_vec_init_kind(cx, init);
            then {
                self.searcher = Some(VecPushSearcher {
                        init: init_kind,
                        name: ident.name,
                        lhs_is_local: true,
                        lhs_span: local.ty.map_or(local.pat.span, |t| local.pat.span.to(t.span)),
                        err_span: local.span,
                        found: 0,
                    });
            }
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if self.searcher.is_none() {
            if_chain! {
                if !in_external_macro(cx.sess(), expr.span);
                if let ExprKind::Assign(left, right, _) = expr.kind;
                if let ExprKind::Path(QPath::Resolved(_, path)) = left.kind;
                if let Some(name) = path.segments.get(0);
                if let Some(init_kind) = get_vec_init_kind(cx, right);
                then {
                    self.searcher = Some(VecPushSearcher {
                        init: init_kind,
                        name: name.ident.name,
                        lhs_is_local: false,
                        lhs_span: left.span,
                        err_span: expr.span,
                        found: 0,
                    });
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
        if let Some(searcher) = self.searcher.take() {
            if_chain! {
                if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind;
                if let ExprKind::MethodCall(path, _, [self_arg, _], _) = expr.kind;
                if path.ident.name.as_str() == "push";
                if let ExprKind::Path(QPath::Resolved(_, self_path)) = self_arg.kind;
                if let [self_name] = self_path.segments;
                if self_name.ident.name == searcher.name;
                then {
                    self.searcher = Some(VecPushSearcher {
                        found: searcher.found + 1,
                        err_span: searcher.err_span.to(stmt.span),
                        .. searcher
                    });
                } else {
                    searcher.display_err(cx);
                }
            }
        }
    }

    fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
        if let Some(searcher) = self.searcher.take() {
            searcher.display_err(cx);
        }
    }
}

fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<VecInitKind> {
    if let ExprKind::Call(func, args) = expr.kind {
        match func.kind {
            ExprKind::Path(QPath::TypeRelative(ty, name))
                if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::vec_type) =>
            {
                if name.ident.name.as_str() == "new" {
                    return Some(VecInitKind::New);
                } else if name.ident.name.as_str() == "with_capacity" {
                    return args.get(0).and_then(|arg| {
                        if_chain! {
                            if let ExprKind::Lit(lit) = &arg.kind;
                            if let LitKind::Int(num, _) = lit.node;
                            then {
                                Some(VecInitKind::WithCapacity(num.try_into().ok()?))
                            } else {
                                None
                            }
                        }
                    });
                }
            }
            ExprKind::Path(QPath::Resolved(_, path))
                if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
                    && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type) =>
            {
                return Some(VecInitKind::New);
            }
            _ => (),
        }
    }
    None
}
<commit_msg>Fix docs: use type inference<commit_after>use crate::utils::{is_type_diagnostic_item, match_def_path, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Local, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol};
use std::convert::TryInto;

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `push` immediately after creating a new `Vec`.
    ///
    /// **Why is this bad?** The `vec![]` macro is both more performant and easier to read than
    /// multiple `push` calls.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// let mut v = Vec::new();
    /// v.push(0);
    /// ```
    /// Use instead:
    /// ```rust
    /// let v = vec![0];
    /// ```
    pub VEC_INIT_THEN_PUSH,
    perf,
    "`push` immediately after `Vec` creation"
}

impl_lint_pass!(VecInitThenPush => [VEC_INIT_THEN_PUSH]);

#[derive(Default)]
pub struct VecInitThenPush {
    searcher: Option<VecPushSearcher>,
}

#[derive(Clone, Copy)]
enum VecInitKind {
    New,
    WithCapacity(u64),
}
struct VecPushSearcher {
    init: VecInitKind,
    name: Symbol,
    lhs_is_local: bool,
    lhs_span: Span,
    err_span: Span,
    found: u64,
}
impl VecPushSearcher {
    fn display_err(&self, cx: &LateContext<'_>) {
        match self.init {
            _ if self.found == 0 => return,
            VecInitKind::WithCapacity(x) if x > self.found => return,
            _ => (),
        };

        let mut s = if self.lhs_is_local {
            String::from("let ")
        } else {
            String::new()
        };
        s.push_str(&snippet(cx, self.lhs_span, ".."));
        s.push_str(" = vec![..];");

        span_lint_and_sugg(
            cx,
            VEC_INIT_THEN_PUSH,
            self.err_span,
            "calls to `push` immediately after creation",
            "consider using the `vec![]` macro",
            s,
            Applicability::HasPlaceholders,
        );
    }
}

impl LateLintPass<'_> for VecInitThenPush {
    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
        self.searcher = None;
        if_chain! {
            if !in_external_macro(cx.sess(), local.span);
            if let Some(init) = local.init;
            if let PatKind::Binding(BindingAnnotation::Mutable, _, ident, None) = local.pat.kind;
            if let Some(init_kind) = get_vec_init_kind(cx, init);
            then {
                self.searcher = Some(VecPushSearcher {
                        init: init_kind,
                        name: ident.name,
                        lhs_is_local: true,
                        lhs_span: local.ty.map_or(local.pat.span, |t| local.pat.span.to(t.span)),
                        err_span: local.span,
                        found: 0,
                    });
            }
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if self.searcher.is_none() {
            if_chain! {
                if !in_external_macro(cx.sess(), expr.span);
                if let ExprKind::Assign(left, right, _) = expr.kind;
                if let ExprKind::Path(QPath::Resolved(_, path)) = left.kind;
                if let Some(name) = path.segments.get(0);
                if let Some(init_kind) = get_vec_init_kind(cx, right);
                then {
                    self.searcher = Some(VecPushSearcher {
                        init: init_kind,
                        name: name.ident.name,
                        lhs_is_local: false,
                        lhs_span: left.span,
                        err_span: expr.span,
                        found: 0,
                    });
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
        if let Some(searcher) = self.searcher.take() {
            if_chain! {
                if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind;
                if let ExprKind::MethodCall(path, _, [self_arg, _], _) = expr.kind;
                if path.ident.name.as_str() == "push";
                if let ExprKind::Path(QPath::Resolved(_, self_path)) = self_arg.kind;
                if let [self_name] = self_path.segments;
                if self_name.ident.name == searcher.name;
                then {
                    self.searcher = Some(VecPushSearcher {
                        found: searcher.found + 1,
                        err_span: searcher.err_span.to(stmt.span),
                        .. searcher
                    });
                } else {
                    searcher.display_err(cx);
                }
            }
        }
    }

    fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
        if let Some(searcher) = self.searcher.take() {
            searcher.display_err(cx);
        }
    }
}

fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<VecInitKind> {
    if let ExprKind::Call(func, args) = expr.kind {
        match func.kind {
            ExprKind::Path(QPath::TypeRelative(ty, name))
                if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::vec_type) =>
            {
                if name.ident.name.as_str() == "new" {
                    return Some(VecInitKind::New);
                } else if name.ident.name.as_str() == "with_capacity" {
                    return args.get(0).and_then(|arg| {
                        if_chain! {
                            if let ExprKind::Lit(lit) = &arg.kind;
                            if let LitKind::Int(num, _) = lit.node;
                            then {
                                Some(VecInitKind::WithCapacity(num.try_into().ok()?))
                            } else {
                                None
                            }
                        }
                    });
                }
            }
            ExprKind::Path(QPath::Resolved(_, path))
                if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
                    && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type) =>
            {
                return Some(VecInitKind::New);
            }
            _ => (),
        }
    }
    None
}
<|endoftext|>