<commit_before>use std::collections::HashMap;
use std::collections::HashSet;
use std::borrow::BorrowMut;
use std::fmt;
use std::fmt::Display;
use std::cmp;

type Id = String;

/// Returns an `Id` with prefix `x` that is not in the set `vars`
fn fresh_var_like(x: &Id, vars: HashSet<Id>) -> Id {
    let mut suffix = 0;
    let mut result = x.clone();
    let len = result.len();
    loop {
        result.push_str(&suffix.to_string());

        if !vars.contains(&result) {
            return result;
        }

        suffix += 1;
        result.truncate(len);
    }
}

#[derive(Debug)]
pub enum EvaluationError {
    UnboundVariable(String),
    IllformedExpression,
}

impl fmt::Display for EvaluationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::EvaluationError::*;
        match *self {
            UnboundVariable(ref id) => write!(f, "Encountered unbound variable: {}", id),
            IllformedExpression => write!(f, "Illformed expression"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Type {
    Var(Id),
    Fun(Box<Type>, Box<Type>),
    Forall(Id, Box<Type>),
}

impl PartialEq for Type {
    /// Equality is defined as alpha-equivalence of types
    fn eq(&self, other: &Type) -> bool {
        use self::Type::*;

        match (self,other) {
            (&Var(ref x),&Var(ref y)) => {
                *x == *y
            },
            (&Fun(ref t1, ref t2),&Fun(ref t3, ref t4)) => {
                *t1 == *t3 && *t2 == *t4
            },
            (&Forall(ref A, ref t1),&Forall(ref B, ref t2)) => {
                t1.subst(&Var(B.clone()), &A) == **t2
            },
            _ => false,
        }
    }
}

impl Eq for Type { }

impl Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Type::Var(ref x) => write!(f,"{}",x),
            Type::Fun(ref a, ref b) => write!(f,"({}) -> {}",a,b),
            Type::Forall(ref x, ref t) => write!(f,"(forall {}. {})", x, t),
        }
    }
}

impl Type {
    /// Returns the result of the capture avoiding substitution `self` {`t`/`X`}
    fn subst(&self, t: &Type, X: &str) -> Type {
        match *self {
            Type::Var(ref Y) => {
                if X == *Y {
                    t.clone()
                } else {
                    self.clone()
                }
            },
            Type::Fun(ref t1, ref t2) => {
                Type::Fun(Box::new(t1.subst(t,X)), Box::new(t2.subst(t,X)))
            },
            Type::Forall(ref Y, ref tau) => {
                if X == *Y {
                    self.clone()
                } else {
                    let mut fvs = t.free_vars();
                    if fvs.contains(Y) {
                        fvs.insert(String::from(X));
                        let fresh_id = fresh_var_like(Y, fvs);
                        let fresh_var = Type::Var(fresh_id.clone());
                        let res = tau.subst(&fresh_var, Y).subst(t, X);
                        Type::Forall(fresh_id, Box::new(res))
                    } else {
                        Type::Forall(Y.clone(), Box::new(tau.subst(t,X)))
                    }
                }
            },
        }
    }

    /// Returns a set the free variables contained in `self`
    fn free_vars(&self) -> HashSet<Id> {
        match *self {
            Type::Var(ref X) => {
                let mut fvs = HashSet::new();
                fvs.insert(X.clone());
                fvs
            },
            Type::Fun(ref t1, ref t2) => {
                let mut fvs = t1.free_vars();
                let mut t2_fvs = t2.free_vars();
                fvs.extend(t2_fvs.drain());
                fvs
            }
            Type::Forall(ref X, ref t) => {
                let mut fvs = t.free_vars();
                fvs.remove(X);
                fvs
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
    Var(Id),
    Lam(Id, Box<Type>, Box<Expr>),
    App(Box<Expr>, Box<Expr>),
    TLam(Id, Box<Expr>),
    TApp(Box<Expr>, Box<Type>),
    Let(Id, Box<Type>, Box<Expr>, Box<Expr>),
    TLet(Id, Box<Type>, Box<Expr>),
}

impl Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Expr::Var(ref x) => write!(f,"{}",x),
            Expr::Lam(ref x, ref t, ref e) => write!(f,"(\\{}:{}.{})",x,t,e),
            Expr::App(ref e1, ref e2) => write!(f,"({} {})",e1,e2),
            Expr::TLam(ref X, ref e) => write!(f,"(/\\{}.{})",X,e),
            Expr::TApp(ref e, ref t) => write!(f,"({} [{}])",e,t),
            Expr::Let(ref x, ref t, ref e1, ref e2) => write!(f,"(let {}:{} = {} in {})",x,t,e1,e2),
            Expr::TLet(ref X, ref t, ref e) => write!(f,"(Let {} = {} in {})",X,t,e),
        }
    }
}

impl Expr {
    /// Returns the normal form of `self` under call-by-value semantics
    pub fn eval(&self) -> Result<Expr,EvaluationError> {
        match *self {
            Expr::Var(ref x) => {
                Err(EvaluationError::UnboundVariable(x.clone()))
            },
            Expr::Lam(_,_,_) | Expr::TLam(_,_) => Ok(self.clone()),
            Expr::App(ref e1, ref e2) => {
                let v1 = e1.eval()?;
                let v2 = e2.eval()?;
                if let Expr::Lam(x,t,e3) = v1 {
                    let new_expr = e3.subst(&v2, &x);
                    new_expr.eval()
                } else {
                    Err(EvaluationError::IllformedExpression)
                }
            },
            Expr::TApp(ref e, ref t) => {
                let v = e.eval()?;
                if let Expr::TLam(X,e) = v {
                    let new_expr = e.subst_type(t, &X);
                    new_expr.eval()
                } else {
                    Err(EvaluationError::IllformedExpression)
                }
            },
            Expr::Let(ref x, ref t, ref e1, ref e2) => {
                Expr::App(
                    Box::new(Expr::Lam(
                        x.clone(),
                        t.clone(),
                        e2.clone())),
                    e1.clone()).eval()
            },
            Expr::TLet(ref X, ref t, ref e) => {
                Expr::TApp(
                    Box::new(Expr::TLam(
                        X.clone(),
                        e.clone())),
                    t.clone()).eval()
            },
        }
    }

    /// Returns the result of the capture avoiding substitution `self` {`e`/`x`}
    fn subst(&self, e: &Expr, x: &str) -> Expr {
        match *self {
            Expr::Var(ref y) => {
                if x == *y {
                    e.clone()
                } else {
                    self.clone()
                }
            },
            Expr::Lam(ref y,ref t,ref e1) => {
                if x == *y {
                    self.clone()
                } else {
                    let mut fvs = e.free_vars();
                    if fvs.contains(y) {
                        fvs.insert(String::from(x));
                        let fresh_id = fresh_var_like(y, fvs);
                        let fresh_var = Expr::Var(fresh_id.clone());
                        let res = e1.subst(&fresh_var, y).subst(e, x);
                        Expr::Lam(fresh_id, t.clone(), Box::new(res))
                    } else {
                        Expr::Lam(y.clone(), t.clone(), Box::new(e1.subst(e, x)))
                    }
                }
            },
            Expr::App(ref e1,ref e2) => {
                Expr::App(Box::new(e1.subst(e,x)), Box::new(e2.subst(e,x)))
            },
            Expr::TLam(ref X,ref e1) => {
                Expr::TLam(X.clone(), Box::new(e1.subst(e,x)))
            },
            Expr::TApp(ref e1,ref t) => {
                Expr::TApp(Box::new(e1.subst(e,x)), t.clone())
            },
            Expr::Let(ref y,ref t,ref e1,ref e2) => {
                let new_e1 = e1.subst(e, x);

                if x == *y {
                    Expr::Let(y.clone(), t.clone(), Box::new(new_e1), e2.clone())
                }
                else {
                    let mut fvs = e.free_vars();
                    if fvs.contains(y) {
                        fvs.insert(String::from(x));
                        let fresh_id = fresh_var_like(y, fvs);
                        let fresh_var = Expr::Var(fresh_id.clone());
                        let new_e2 = e2.subst(&fresh_var, y).subst(e, x);
                        Expr::Let(fresh_id, t.clone(), Box::new(new_e1), Box::new(new_e2))
                    }
                    else {
                        Expr::Let(y.clone(), t.clone(), Box::new(new_e1), Box::new(e2.subst(e, x)))
                    }
                }
            },
            Expr::TLet(ref X,ref t,ref e1) => {
                Expr::TLet(X.clone(), t.clone(), Box::new(e1.subst(e,x)))
            },
        }
    }

    fn subst_type(&self, to: &Type, from: &str) -> Expr {
        match *self {
            Expr::Var(ref y) => {
                self.clone()
            },
            Expr::Lam(ref y,ref t,ref e1) => {
                let new_t = t.subst(to, from);
                Expr::Lam(y.clone(), Box::new(new_t), Box::new(e1.subst_type(to,from)))
            },
            Expr::App(ref e1,ref e2) => {
                Expr::App(Box::new(e1.subst_type(to,from)), Box::new(e2.subst_type(to,from)))
            },
            Expr::TLam(ref X,ref e1) => {
                if *X == from {
                    self.clone()
                } else {
                    unimplemented!()
                }
            },
            Expr::TApp(ref e1,ref t) => {
                let new_t = t.subst(to, from);
                let new_e1 = e1.subst_type(to, from);
                Expr::TApp(Box::new(new_e1), Box::new(new_t))
            },
            Expr::Let(ref y,ref t,ref e1,ref e2) => {
                let new_t = t.subst(to, from);
                let new_e1 = e1.subst_type(to, from);
                let new_e2 = e2.subst_type(to, from);
                Expr::Let(y.clone(), Box::new(new_t), Box::new(new_e1), Box::new(new_e2))
            },
            Expr::TLet(ref X,ref t,ref e1) => {
                let new_t = t.subst(to, from);
                if *X == from {
                    Expr::TLet(X.clone(), Box::new(new_t), e1.clone())
                }
                else {
                    unimplemented!()
                }
            },
        }
    }

    /// Returns a set the free variables contained in `self`
    fn free_vars(&self) -> HashSet<Id> {
        match *self {
            Expr::Var(ref x) => {
                let mut vars = HashSet::new();
                vars.insert(x.clone());
                vars
            },
            Expr::Lam(ref x, _, ref e) => {
                let mut vars = e.free_vars();
                vars.remove(x);
                vars
            },
            Expr::App(ref e1, ref e2) => {
                let mut vars = e1.free_vars();
                let mut e2_vars = e2.free_vars();
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLam(_, ref e) => {
                e.free_vars()
            },
            Expr::TApp(ref e, _) => {
                e.free_vars()
            },
            Expr::Let(ref x, _, ref e1, ref e2) => {
                let mut vars = e1.free_vars();
                let mut e2_vars = e2.free_vars();
                e2_vars.remove(x);
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLet(_, _, ref e) => {
                e.free_vars()
            }
        }
    }

    /// Returns a set the free type variables contained in `self`
    fn free_type_vars(&self) -> HashSet<Id> {
        match *self {
            Expr::Var(_) => {
                HashSet::new()
            },
            Expr::Lam(_, ref t, ref e) => {
                let mut vars = t.free_vars();
                let mut e_vars = e.free_type_vars();
                vars.extend(e_vars.drain());
                vars
            },
            Expr::App(ref e1, ref e2) => {
                let mut vars = e1.free_type_vars();
                let mut e2_vars = e2.free_type_vars();
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLam(ref X, ref e) => {
                let mut vars = e.free_type_vars();
                vars.remove(X);
                vars
            },
            Expr::TApp(ref e, ref t) => {
                let mut vars = e.free_type_vars();
                let mut t_vars = e.free_vars();
                vars.extend(t_vars.drain());
                vars
            },
            Expr::Let(_, ref t, ref e1, ref e2) => {
                let mut vars = t.free_vars();
                let mut e1_vars = e1.free_type_vars();
                let mut e2_vars = e2.free_type_vars();
                vars.extend(e1_vars.drain());
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLet(ref X, ref t, ref e) => {
                let mut vars = t.free_vars();
                let mut e_vars = e.free_type_vars();
                e_vars.remove(X);
                vars.extend(e_vars.drain());
                vars
            }
        }
    }
}<commit_msg>Finish first round of eval<commit_after>use std::collections::HashMap;
use std::collections::HashSet;
use std::borrow::BorrowMut;
use std::fmt;
use std::fmt::Display;
use std::cmp;

type Id = String;

/// Returns an `Id` with prefix `x` that is not in the set `vars`
fn fresh_var_like(x: &Id, vars: HashSet<Id>) -> Id {
    let mut suffix = 0;
    let mut result = x.clone();
    let len = result.len();
    loop {
        result.push_str(&suffix.to_string());

        if !vars.contains(&result) {
            return result;
        }

        suffix += 1;
        result.truncate(len);
    }
}

#[derive(Debug)]
pub enum EvaluationError {
    UnboundVariable(String),
    IllformedExpression,
}

impl fmt::Display for EvaluationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::EvaluationError::*;
        match *self {
            UnboundVariable(ref id) => write!(f, "Encountered unbound variable: {}", id),
            IllformedExpression => write!(f, "Illformed expression"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Type {
    Var(Id),
    Fun(Box<Type>, Box<Type>),
    Forall(Id, Box<Type>),
}

impl PartialEq for Type {
    /// Equality is defined as alpha-equivalence of types
    fn eq(&self, other: &Type) -> bool {
        use self::Type::*;

        match (self,other) {
            (&Var(ref x),&Var(ref y)) => {
                *x == *y
            },
            (&Fun(ref t1, ref t2),&Fun(ref t3, ref t4)) => {
                *t1 == *t3 && *t2 == *t4
            },
            (&Forall(ref A, ref t1),&Forall(ref B, ref t2)) => {
                t1.subst(&Var(B.clone()), &A) == **t2
            },
            _ => false,
        }
    }
}

impl Eq for Type { }

impl Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Type::Var(ref x) => write!(f,"{}",x),
            Type::Fun(ref a, ref b) => write!(f,"({}) -> {}",a,b),
            Type::Forall(ref x, ref t) => write!(f,"(forall {}. {})", x, t),
        }
    }
}

impl Type {
    /// Returns the result of the capture avoiding substitution `self` {`t`/`X`}
    fn subst(&self, t: &Type, X: &str) -> Type {
        match *self {
            Type::Var(ref Y) => {
                if X == *Y {
                    t.clone()
                } else {
                    self.clone()
                }
            },
            Type::Fun(ref t1, ref t2) => {
                Type::Fun(Box::new(t1.subst(t,X)), Box::new(t2.subst(t,X)))
            },
            Type::Forall(ref Y, ref tau) => {
                if X == *Y {
                    self.clone()
                } else {
                    let mut fvs = t.free_vars();
                    if fvs.contains(Y) {
                        fvs.insert(String::from(X));
                        let fresh_id = fresh_var_like(Y, fvs);
                        let fresh_var = Type::Var(fresh_id.clone());
                        let res = tau.subst(&fresh_var, Y).subst(t, X);
                        Type::Forall(fresh_id, Box::new(res))
                    } else {
                        Type::Forall(Y.clone(), Box::new(tau.subst(t,X)))
                    }
                }
            },
        }
    }

    /// Returns a set the free variables contained in `self`
    fn free_vars(&self) -> HashSet<Id> {
        match *self {
            Type::Var(ref X) => {
                let mut fvs = HashSet::new();
                fvs.insert(X.clone());
                fvs
            },
            Type::Fun(ref t1, ref t2) => {
                let mut fvs = t1.free_vars();
                let mut t2_fvs = t2.free_vars();
                fvs.extend(t2_fvs.drain());
                fvs
            }
            Type::Forall(ref X, ref t) => {
                let mut fvs = t.free_vars();
                fvs.remove(X);
                fvs
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
    Var(Id),
    Lam(Id, Box<Type>, Box<Expr>),
    App(Box<Expr>, Box<Expr>),
    TLam(Id, Box<Expr>),
    TApp(Box<Expr>, Box<Type>),
    Let(Id, Box<Type>, Box<Expr>, Box<Expr>),
    TLet(Id, Box<Type>, Box<Expr>),
}

impl Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Expr::Var(ref x) => write!(f,"{}",x),
            Expr::Lam(ref x, ref t, ref e) => write!(f,"(\\{}:{}.{})",x,t,e),
            Expr::App(ref e1, ref e2) => write!(f,"({} {})",e1,e2),
            Expr::TLam(ref X, ref e) => write!(f,"(/\\{}.{})",X,e),
            Expr::TApp(ref e, ref t) => write!(f,"({} [{}])",e,t),
            Expr::Let(ref x, ref t, ref e1, ref e2) => write!(f,"(let {}:{} = {} in {})",x,t,e1,e2),
            Expr::TLet(ref X, ref t, ref e) => write!(f,"(Let {} = {} in {})",X,t,e),
        }
    }
}

impl Expr {
    /// Returns the normal form of `self` under call-by-value semantics
    pub fn eval(&self) -> Result<Expr,EvaluationError> {
        match *self {
            Expr::Var(ref x) => {
                Err(EvaluationError::UnboundVariable(x.clone()))
            },
            Expr::Lam(_,_,_) | Expr::TLam(_,_) => Ok(self.clone()),
            Expr::App(ref e1, ref e2) => {
                let v1 = e1.eval()?;
                let v2 = e2.eval()?;
                if let Expr::Lam(x,t,e3) = v1 {
                    let new_expr = e3.subst(&v2, &x);
                    new_expr.eval()
                } else {
                    Err(EvaluationError::IllformedExpression)
                }
            },
            Expr::TApp(ref e, ref t) => {
                let v = e.eval()?;
                if let Expr::TLam(X,e) = v {
                    let new_expr = e.subst_type(t, &X);
                    new_expr.eval()
                } else {
                    Err(EvaluationError::IllformedExpression)
                }
            },
            Expr::Let(ref x, ref t, ref e1, ref e2) => {
                Expr::App(
                    Box::new(Expr::Lam(
                        x.clone(),
                        t.clone(),
                        e2.clone())),
                    e1.clone()).eval()
            },
            Expr::TLet(ref X, ref t, ref e) => {
                Expr::TApp(
                    Box::new(Expr::TLam(
                        X.clone(),
                        e.clone())),
                    t.clone()).eval()
            },
        }
    }

    /// Returns the result of the capture avoiding substitution `self` {`e`/`x`}
    fn subst(&self, e: &Expr, x: &str) -> Expr {
        match *self {
            Expr::Var(ref y) => {
                if x == *y {
                    e.clone()
                } else {
                    self.clone()
                }
            },
            Expr::Lam(ref y,ref t,ref e1) => {
                if x == *y {
                    self.clone()
                } else {
                    let mut fvs = e.free_vars();
                    if fvs.contains(y) {
                        fvs.insert(String::from(x));
                        let fresh_id = fresh_var_like(y, fvs);
                        let fresh_var = Expr::Var(fresh_id.clone());
                        let res = e1.subst(&fresh_var, y).subst(e, x);
                        Expr::Lam(fresh_id, t.clone(), Box::new(res))
                    } else {
                        Expr::Lam(y.clone(), t.clone(), Box::new(e1.subst(e, x)))
                    }
                }
            },
            Expr::App(ref e1,ref e2) => {
                Expr::App(Box::new(e1.subst(e,x)), Box::new(e2.subst(e,x)))
            },
            Expr::TLam(ref X,ref e1) => {
                Expr::TLam(X.clone(), Box::new(e1.subst(e,x)))
            },
            Expr::TApp(ref e1,ref t) => {
                Expr::TApp(Box::new(e1.subst(e,x)), t.clone())
            },
            Expr::Let(ref y,ref t,ref e1,ref e2) => {
                let new_e1 = e1.subst(e, x);

                if x == *y {
                    Expr::Let(y.clone(), t.clone(), Box::new(new_e1), e2.clone())
                }
                else {
                    let mut fvs = e.free_vars();
                    if fvs.contains(y) {
                        fvs.insert(String::from(x));
                        let fresh_id = fresh_var_like(y, fvs);
                        let fresh_var = Expr::Var(fresh_id.clone());
                        let new_e2 = e2.subst(&fresh_var, y).subst(e, x);
                        Expr::Let(fresh_id, t.clone(), Box::new(new_e1), Box::new(new_e2))
                    }
                    else {
                        Expr::Let(y.clone(), t.clone(), Box::new(new_e1), Box::new(e2.subst(e, x)))
                    }
                }
            },
            Expr::TLet(ref X,ref t,ref e1) => {
                Expr::TLet(X.clone(), t.clone(), Box::new(e1.subst(e,x)))
            },
        }
    }

    fn subst_type(&self, to: &Type, from: &str) -> Expr {
        match *self {
            Expr::Var(ref y) => {
                self.clone()
            },
            Expr::Lam(ref y,ref t,ref e1) => {
                let new_t = t.subst(to, from);
                Expr::Lam(y.clone(), Box::new(new_t), Box::new(e1.subst_type(to,from)))
            },
            Expr::App(ref e1,ref e2) => {
                Expr::App(Box::new(e1.subst_type(to,from)), Box::new(e2.subst_type(to,from)))
            },
            Expr::TLam(ref X,ref e1) => {
                if *X == from {
                    self.clone()
                } else {
                    let mut fvs = to.free_vars();
                    if fvs.contains(X) {
                        fvs.insert(String::from(from));
                        let fresh_id = fresh_var_like(X, fvs);
                        let fresh_var = Type::Var(fresh_id.clone());
                        let new_e1 = e1.subst_type(&fresh_var, X).subst_type(to, from);
                        Expr::TLam(fresh_id, Box::new(new_e1))
                    } else {
                        Expr::TLam(X.clone(), Box::new(e1.subst_type(to, from)))
                    }
                }
            },
            Expr::TApp(ref e1,ref t) => {
                let new_t = t.subst(to, from);
                let new_e1 = e1.subst_type(to, from);
                Expr::TApp(Box::new(new_e1), Box::new(new_t))
            },
            Expr::Let(ref y,ref t,ref e1,ref e2) => {
                let new_t = t.subst(to, from);
                let new_e1 = e1.subst_type(to, from);
                let new_e2 = e2.subst_type(to, from);
                Expr::Let(y.clone(), Box::new(new_t), Box::new(new_e1), Box::new(new_e2))
            },
            Expr::TLet(ref X,ref t,ref e1) => {
                let new_t = t.subst(to, from);
                if *X == from {
                    Expr::TLet(X.clone(), Box::new(new_t), e1.clone())
                }
                else {
                    let mut fvs = to.free_vars();
                    if fvs.contains(X) {
                        fvs.insert(String::from(from));
                        let fresh_id = fresh_var_like(X, fvs);
                        let fresh_var = Type::Var(fresh_id.clone());
                        let new_e1 = e1.subst_type(&fresh_var, X).subst_type(to, from);
                        Expr::TLet(fresh_id, Box::new(new_t), Box::new(new_e1))
                    } else {
                        Expr::TLet(X.clone(), Box::new(new_t), Box::new(e1.subst_type(to, from)))
                    }
                }
            },
        }
    }

    /// Returns a set the free variables contained in `self`
    fn free_vars(&self) -> HashSet<Id> {
        match *self {
            Expr::Var(ref x) => {
                let mut vars = HashSet::new();
                vars.insert(x.clone());
                vars
            },
            Expr::Lam(ref x, _, ref e) => {
                let mut vars = e.free_vars();
                vars.remove(x);
                vars
            },
            Expr::App(ref e1, ref e2) => {
                let mut vars = e1.free_vars();
                let mut e2_vars = e2.free_vars();
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLam(_, ref e) => {
                e.free_vars()
            },
            Expr::TApp(ref e, _) => {
                e.free_vars()
            },
            Expr::Let(ref x, _, ref e1, ref e2) => {
                let mut vars = e1.free_vars();
                let mut e2_vars = e2.free_vars();
                e2_vars.remove(x);
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLet(_, _, ref e) => {
                e.free_vars()
            }
        }
    }

    /// Returns a set the free type variables contained in `self`
    fn free_type_vars(&self) -> HashSet<Id> {
        match *self {
            Expr::Var(_) => {
                HashSet::new()
            },
            Expr::Lam(_, ref t, ref e) => {
                let mut vars = t.free_vars();
                let mut e_vars = e.free_type_vars();
                vars.extend(e_vars.drain());
                vars
            },
            Expr::App(ref e1, ref e2) => {
                let mut vars = e1.free_type_vars();
                let mut e2_vars = e2.free_type_vars();
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLam(ref X, ref e) => {
                let mut vars = e.free_type_vars();
                vars.remove(X);
                vars
            },
            Expr::TApp(ref e, ref t) => {
                let mut vars = e.free_type_vars();
                let mut t_vars = e.free_vars();
                vars.extend(t_vars.drain());
                vars
            },
            Expr::Let(_, ref t, ref e1, ref e2) => {
                let mut vars = t.free_vars();
                let mut e1_vars = e1.free_type_vars();
                let mut e2_vars = e2.free_type_vars();
                vars.extend(e1_vars.drain());
                vars.extend(e2_vars.drain());
                vars
            },
            Expr::TLet(ref X, ref t, ref e) => {
                let mut vars = t.free_vars();
                let mut e_vars = e.free_type_vars();
                e_vars.remove(X);
                vars.extend(e_vars.drain());
                vars
            }
        }
    }
}<|endoftext|>


<commit_before>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa_foundation::foundation::{NSRange, NSUInteger};
use objc::runtime::{NO, YES};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum MTLTextureType {
    D1 = 0,
    D1Array = 1,
    D2 = 2,
    D2Array = 3,
    D2Multisample = 4,
    Cube = 5,
    CubeArray = 6,
    D3 = 7,
}

bitflags! {
    pub struct MTLTextureUsage: NSUInteger {
        const Unknown         = 0x0000;
        const ShaderRead      = 0x0001;
        const ShaderWrite     = 0x0002;
        const RenderTarget    = 0x0004;
        const PixelFormatView = 0x0010;
    }
}

pub enum MTLTextureDescriptor {}

foreign_obj_type! {
    type CType = MTLTextureDescriptor;
    pub struct TextureDescriptor;
    pub struct TextureDescriptorRef;
}

impl TextureDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLTextureDescriptor);
            msg_send![class, new]
        }
    }
}

impl TextureDescriptorRef {
    pub fn texture_type(&self) -> MTLTextureType {
        unsafe { msg_send![self, textureType] }
    }

    pub fn set_texture_type(&self, texture_type: MTLTextureType) {
        unsafe { msg_send![self, setTextureType: texture_type] }
    }

    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setPixelFormat: pixel_format] }
    }

    pub fn width(&self) -> NSUInteger {
        unsafe { msg_send![self, width] }
    }

    pub fn set_width(&self, width: NSUInteger) {
        unsafe { msg_send![self, setWidth: width] }
    }

    pub fn height(&self) -> NSUInteger {
        unsafe { msg_send![self, height] }
    }

    pub fn set_height(&self, height: NSUInteger) {
        unsafe { msg_send![self, setHeight: height] }
    }

    pub fn depth(&self) -> NSUInteger {
        unsafe { msg_send![self, depth] }
    }

    pub fn set_depth(&self, depth: NSUInteger) {
        unsafe { msg_send![self, setDepth: depth] }
    }

    pub fn mipmap_level_count(&self) -> NSUInteger {
        unsafe { msg_send![self, mipmapLevelCount] }
    }

    pub fn set_mipmap_level_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setMipmapLevelCount: count] }
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn set_sample_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setSampleCount: count] }
    }

    pub fn array_length(&self) -> NSUInteger {
        unsafe { msg_send![self, arrayLength] }
    }

    pub fn set_array_length(&self, length: NSUInteger) {
        unsafe { msg_send![self, setArrayLength: length] }
    }

    pub fn resource_options(&self) -> MTLResourceOptions {
        unsafe { msg_send![self, resourceOptions] }
    }

    pub fn set_resource_options(&self, options: MTLResourceOptions) {
        unsafe { msg_send![self, setResourceOptions: options] }
    }

    pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
        unsafe { msg_send![self, cpuCacheMode] }
    }

    pub fn set_cpu_cache_mode(&self, mode: MTLCPUCacheMode) {
        unsafe { msg_send![self, setCpuCacheMode: mode] }
    }

    pub fn storage_mode(&self) -> MTLStorageMode {
        unsafe { msg_send![self, storageMode] }
    }

    pub fn set_storage_mode(&self, mode: MTLStorageMode) {
        unsafe { msg_send![self, setStorageMode: mode] }
    }

    pub fn usage(&self) -> MTLTextureUsage {
        unsafe { msg_send![self, usage] }
    }

    pub fn set_usage(&self, usage: MTLTextureUsage) {
        unsafe { msg_send![self, setUsage: usage] }
    }
}

pub enum MTLTexture {}

foreign_obj_type! {
    type CType = MTLTexture;
    pub struct Texture;
    pub struct TextureRef;
    type ParentType = ResourceRef;
}

impl TextureRef {
    #[deprecated(since = "0.13.0")]
    pub fn root_resource(&self) -> Option<&ResourceRef> {
        unsafe { msg_send![self, rootResource] }
    }

    pub fn parent_texture(&self) -> Option<&TextureRef> {
        unsafe { msg_send![self, parentTexture] }
    }

    pub fn parent_relative_level(&self) -> NSUInteger {
        unsafe { msg_send![self, parentRelativeLevel] }
    }

    pub fn parent_relative_slice(&self) -> NSUInteger {
        unsafe { msg_send![self, parentRelativeSlice] }
    }

    pub fn buffer(&self) -> Option<&BufferRef> {
        unsafe { msg_send![self, buffer] }
    }

    pub fn buffer_offset(&self) -> NSUInteger {
        unsafe { msg_send![self, bufferOffset] }
    }

    pub fn buffer_stride(&self) -> NSUInteger {
        unsafe { msg_send![self, bufferBytesPerRow] }
    }

    pub fn texture_type(&self) -> MTLTextureType {
        unsafe { msg_send![self, textureType] }
    }

    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn width(&self) -> NSUInteger {
        unsafe { msg_send![self, width] }
    }

    pub fn height(&self) -> NSUInteger {
        unsafe { msg_send![self, height] }
    }

    pub fn depth(&self) -> NSUInteger {
        unsafe { msg_send![self, depth] }
    }

    pub fn mipmap_level_count(&self) -> NSUInteger {
        unsafe { msg_send![self, mipmapLevelCount] }
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn array_length(&self) -> NSUInteger {
        unsafe { msg_send![self, arrayLength] }
    }

    pub fn usage(&self) -> MTLTextureUsage {
        unsafe { msg_send![self, usage] }
    }

    /// [framebufferOnly Apple Docs](https://developer.apple.com/documentation/metal/mtltexture/1515749-framebufferonly?language=objc)
    pub fn framebuffer_only(&self) -> bool {
        unsafe {
            match msg_send![self, isFramebufferOnly] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn get_bytes(
        &self,
        bytes: *mut std::ffi::c_void,
        stride: NSUInteger,
        region: MTLRegion,
        mipmap_level: NSUInteger,
    ) {
        unsafe {
            msg_send![self, getBytes:bytes
                         bytesPerRow:stride
                          fromRegion:region
                         mipmapLevel:mipmap_level]
        }
    }

    pub fn get_bytes_in_slice(
        &self,
        bytes: *mut std::ffi::c_void,
        stride: NSUInteger,
        image_stride: NSUInteger,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        slice: NSUInteger,
    ) {
        unsafe {
            msg_send![self, getBytes:bytes
                         bytesPerRow:stride
                       bytesPerImage:image_stride
                          fromRegion:region
                         mipmapLevel:mipmap_level
                               slice:slice]
        }
    }

    pub fn replace_region(
        &self,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        bytes: *const std::ffi::c_void,
        stride: NSUInteger,
    ) {
        unsafe {
            msg_send![self, replaceRegion:region
                              mipmapLevel:mipmap_level
                                withBytes:bytes
                              bytesPerRow:stride]
        }
    }

    pub fn replace_region_in_slice(
        &self,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        slice: NSUInteger,
        bytes: *const std::ffi::c_void,
        stride: NSUInteger,
        image_stride: NSUInteger,
    ) {
        unsafe {
            msg_send![self, replaceRegion:region
                              mipmapLevel:mipmap_level
                                    slice:slice
                                withBytes:bytes
                              bytesPerRow:stride
                            bytesPerImage:image_stride]
        }
    }

    pub fn new_texture_view(&self, pixel_format: MTLPixelFormat) -> Texture {
        unsafe { msg_send![self, newTextureViewWithPixelFormat: pixel_format] }
    }

    pub fn new_texture_view_from_slice(
        &self,
        pixel_format: MTLPixelFormat,
        texture_type: MTLTextureType,
        mipmap_levels: NSRange,
        slices: NSRange,
    ) -> Texture {
        unsafe {
            msg_send![self, newTextureViewWithPixelFormat:pixel_format
                                                textureType:texture_type
                                                     levels:mipmap_levels
                                                     slices:slices]
        }
    }
}
<commit_msg>added set_mipmap_level_count_for_size helper function (#163)<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa_foundation::foundation::{NSRange, NSUInteger};
use objc::runtime::{NO, YES};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum MTLTextureType {
    D1 = 0,
    D1Array = 1,
    D2 = 2,
    D2Array = 3,
    D2Multisample = 4,
    Cube = 5,
    CubeArray = 6,
    D3 = 7,
}

bitflags! {
    pub struct MTLTextureUsage: NSUInteger {
        const Unknown         = 0x0000;
        const ShaderRead      = 0x0001;
        const ShaderWrite     = 0x0002;
        const RenderTarget    = 0x0004;
        const PixelFormatView = 0x0010;
    }
}

pub enum MTLTextureDescriptor {}

foreign_obj_type! {
    type CType = MTLTextureDescriptor;
    pub struct TextureDescriptor;
    pub struct TextureDescriptorRef;
}

impl TextureDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLTextureDescriptor);
            msg_send![class, new]
        }
    }
}

impl TextureDescriptorRef {
    pub fn texture_type(&self) -> MTLTextureType {
        unsafe { msg_send![self, textureType] }
    }

    pub fn set_texture_type(&self, texture_type: MTLTextureType) {
        unsafe { msg_send![self, setTextureType: texture_type] }
    }

    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setPixelFormat: pixel_format] }
    }

    pub fn width(&self) -> NSUInteger {
        unsafe { msg_send![self, width] }
    }

    pub fn set_width(&self, width: NSUInteger) {
        unsafe { msg_send![self, setWidth: width] }
    }

    pub fn height(&self) -> NSUInteger {
        unsafe { msg_send![self, height] }
    }

    pub fn set_height(&self, height: NSUInteger) {
        unsafe { msg_send![self, setHeight: height] }
    }

    pub fn depth(&self) -> NSUInteger {
        unsafe { msg_send![self, depth] }
    }

    pub fn set_depth(&self, depth: NSUInteger) {
        unsafe { msg_send![self, setDepth: depth] }
    }

    pub fn mipmap_level_count(&self) -> NSUInteger {
        unsafe { msg_send![self, mipmapLevelCount] }
    }

    pub fn set_mipmap_level_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setMipmapLevelCount: count] }
    }

    pub fn set_mipmap_level_count_for_size(&self, size: MTLSize) {
        let MTLSize {
            width,
            height,
            depth,
        } = size;
        let count = (width.max(height).max(depth) as f64).log2().ceil() as u64;
        self.set_mipmap_level_count(count);
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn set_sample_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setSampleCount: count] }
    }

    pub fn array_length(&self) -> NSUInteger {
        unsafe { msg_send![self, arrayLength] }
    }

    pub fn set_array_length(&self, length: NSUInteger) {
        unsafe { msg_send![self, setArrayLength: length] }
    }

    pub fn resource_options(&self) -> MTLResourceOptions {
        unsafe { msg_send![self, resourceOptions] }
    }

    pub fn set_resource_options(&self, options: MTLResourceOptions) {
        unsafe { msg_send![self, setResourceOptions: options] }
    }

    pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
        unsafe { msg_send![self, cpuCacheMode] }
    }

    pub fn set_cpu_cache_mode(&self, mode: MTLCPUCacheMode) {
        unsafe { msg_send![self, setCpuCacheMode: mode] }
    }

    pub fn storage_mode(&self) -> MTLStorageMode {
        unsafe { msg_send![self, storageMode] }
    }

    pub fn set_storage_mode(&self, mode: MTLStorageMode) {
        unsafe { msg_send![self, setStorageMode: mode] }
    }

    pub fn usage(&self) -> MTLTextureUsage {
        unsafe { msg_send![self, usage] }
    }

    pub fn set_usage(&self, usage: MTLTextureUsage) {
        unsafe { msg_send![self, setUsage: usage] }
    }
}

pub enum MTLTexture {}

foreign_obj_type! {
    type CType = MTLTexture;
    pub struct Texture;
    pub struct TextureRef;
    type ParentType = ResourceRef;
}

impl TextureRef {
    #[deprecated(since = "0.13.0")]
    pub fn root_resource(&self) -> Option<&ResourceRef> {
        unsafe { msg_send![self, rootResource] }
    }

    pub fn parent_texture(&self) -> Option<&TextureRef> {
        unsafe { msg_send![self, parentTexture] }
    }

    pub fn parent_relative_level(&self) -> NSUInteger {
        unsafe { msg_send![self, parentRelativeLevel] }
    }

    pub fn parent_relative_slice(&self) -> NSUInteger {
        unsafe { msg_send![self, parentRelativeSlice] }
    }

    pub fn buffer(&self) -> Option<&BufferRef> {
        unsafe { msg_send![self, buffer] }
    }

    pub fn buffer_offset(&self) -> NSUInteger {
        unsafe { msg_send![self, bufferOffset] }
    }

    pub fn buffer_stride(&self) -> NSUInteger {
        unsafe { msg_send![self, bufferBytesPerRow] }
    }

    pub fn texture_type(&self) -> MTLTextureType {
        unsafe { msg_send![self, textureType] }
    }

    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn width(&self) -> NSUInteger {
        unsafe { msg_send![self, width] }
    }

    pub fn height(&self) -> NSUInteger {
        unsafe { msg_send![self, height] }
    }

    pub fn depth(&self) -> NSUInteger {
        unsafe { msg_send![self, depth] }
    }

    pub fn mipmap_level_count(&self) -> NSUInteger {
        unsafe { msg_send![self, mipmapLevelCount] }
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn array_length(&self) -> NSUInteger {
        unsafe { msg_send![self, arrayLength] }
    }

    pub fn usage(&self) -> MTLTextureUsage {
        unsafe { msg_send![self, usage] }
    }

    /// [framebufferOnly Apple Docs](https://developer.apple.com/documentation/metal/mtltexture/1515749-framebufferonly?language=objc)
    pub fn framebuffer_only(&self) -> bool {
        unsafe {
            match msg_send![self, isFramebufferOnly] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn get_bytes(
        &self,
        bytes: *mut std::ffi::c_void,
        stride: NSUInteger,
        region: MTLRegion,
        mipmap_level: NSUInteger,
    ) {
        unsafe {
            msg_send![self, getBytes:bytes
                         bytesPerRow:stride
                          fromRegion:region
                         mipmapLevel:mipmap_level]
        }
    }

    pub fn get_bytes_in_slice(
        &self,
        bytes: *mut std::ffi::c_void,
        stride: NSUInteger,
        image_stride: NSUInteger,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        slice: NSUInteger,
    ) {
        unsafe {
            msg_send![self, getBytes:bytes
                         bytesPerRow:stride
                       bytesPerImage:image_stride
                          fromRegion:region
                         mipmapLevel:mipmap_level
                               slice:slice]
        }
    }

    pub fn replace_region(
        &self,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        bytes: *const std::ffi::c_void,
        stride: NSUInteger,
    ) {
        unsafe {
            msg_send![self, replaceRegion:region
                              mipmapLevel:mipmap_level
                                withBytes:bytes
                              bytesPerRow:stride]
        }
    }

    pub fn replace_region_in_slice(
        &self,
        region: MTLRegion,
        mipmap_level: NSUInteger,
        slice: NSUInteger,
        bytes: *const std::ffi::c_void,
        stride: NSUInteger,
        image_stride: NSUInteger,
    ) {
        unsafe {
            msg_send![self, replaceRegion:region
                              mipmapLevel:mipmap_level
                                    slice:slice
                                withBytes:bytes
                              bytesPerRow:stride
                            bytesPerImage:image_stride]
        }
    }

    pub fn new_texture_view(&self, pixel_format: MTLPixelFormat) -> Texture {
        unsafe { msg_send![self, newTextureViewWithPixelFormat: pixel_format] }
    }

    pub fn new_texture_view_from_slice(
        &self,
        pixel_format: MTLPixelFormat,
        texture_type: MTLTextureType,
        mipmap_levels: NSRange,
        slices: NSRange,
    ) -> Texture {
        unsafe {
            msg_send![self, newTextureViewWithPixelFormat:pixel_format
                                                textureType:texture_type
                                                     levels:mipmap_levels
                                                     slices:slices]
        }
    }
}
<|endoftext|>


<commit_before>use std::net::IpAddr;

use maxminddb::geoip2;

fn main() -> Result<(), String>{
    let mut args = std::env::args().skip(1);
    let reader =
        maxminddb::Reader::open_readfile(args.next().ok_or_else(|| "First argument must be the path to the IP database")?).unwrap();
    let ip: IpAddr = args.next().ok_or_else(|| "Second argument must be the IP address, like 128.101.101.101")?.parse().unwrap();
    let city: geoip2::City = reader.lookup(ip).unwrap();
    println!("{:#?}", city);
    Ok(())
}
<commit_msg>Run cargo fmt<commit_after>use std::net::IpAddr;

use maxminddb::geoip2;

fn main() -> Result<(), String> {
    let mut args = std::env::args().skip(1);
    let reader = maxminddb::Reader::open_readfile(
        args.next()
            .ok_or_else(|| "First argument must be the path to the IP database")?,
    )
    .unwrap();
    let ip: IpAddr = args
        .next()
        .ok_or_else(|| "Second argument must be the IP address, like 128.101.101.101")?
        .parse()
        .unwrap();
    let city: geoip2::City = reader.lookup(ip).unwrap();
    println!("{:#?}", city);
    Ok(())
}
<|endoftext|>


<commit_before>extern crate egg_mode;

mod common;

use egg_mode::search::{self, ResultType, Distance};

fn main() {
    let config = common::Config::load();

    //rust tweets around dallas
    let search = search::search("rustlang")
                        .result_type(ResultType::Recent)
                        .count(10)
                        .call(&config.con_token, &config.access_token)
                        .unwrap();

    for tweet in &search.response.statuses {
        common::print_tweet(tweet);
    }
}
<commit_msg>remove unused import in examples/search<commit_after>extern crate egg_mode;

mod common;

use egg_mode::search::{self, ResultType};

fn main() {
    let config = common::Config::load();

    //rust tweets around dallas
    let search = search::search("rustlang")
                        .result_type(ResultType::Recent)
                        .count(10)
                        .call(&config.con_token, &config.access_token)
                        .unwrap();

    for tweet in &search.response.statuses {
        common::print_tweet(tweet);
    }
}
<|endoftext|>


<commit_before>extern crate orbclient;

use orbclient::{Color, EventOption, GraphicsPath, Mode, Renderer, Window};

fn main() {
    let (width, height) = orbclient::get_display_size().unwrap();

    let mut window = Window::new(
        (width as i32) / 4,
        (height as i32) / 4,
        width / 2,
        height / 2,
        "TITLE",
    )
    .unwrap();

    let (win_w, win_h) = (width / 2, height / 2);

    // top left -> bottom rigth
    window.linear_gradient(
        0,
        0,
        win_w / 3,
        win_h,
        0,
        0,
        (win_w / 3) as i32,
        (win_h / 2) as i32,
        Color::rgb(128, 128, 128),
        Color::rgb(255, 255, 255),
    );
    // horizontal gradient
    window.linear_gradient(
        (win_w / 3) as i32,
        0,
        win_w / 3,
        win_h,
        (win_w / 3) as i32,
        0,
        (2 * win_w / 3) as i32,
        0,
        Color::rgb(128, 255, 255),
        Color::rgb(255, 255, 255),
    );
    // vertical gradient
    window.linear_gradient(
        (2 * win_w / 3) as i32,
        0,
        win_w / 3,
        win_h,
        (2 * win_w / 3) as i32,
        0,
        (2 * win_w / 3) as i32,
        win_h as i32,
        Color::rgb(0, 128, 0),
        Color::rgb(255, 255, 255),
    );
    window.arc(100, 100, -25, 1 << 0 | 1 << 2, Color::rgb(0, 0, 255));
    window.arc(100, 100, -25, 1 << 1 | 1 << 3, Color::rgb(0, 255, 255));
    window.arc(100, 100, -25, 1 << 4 | 1 << 6, Color::rgb(255, 0, 255));
    window.arc(100, 100, -25, 1 << 5 | 1 << 7, Color::rgb(255, 255, 0));
    window.circle(100, 100, 25, Color::rgb(0, 0, 0));
    window.circle(100, 101, -25, Color::rgb(0, 255, 0));
    window.circle(220, 220, -100, Color::rgba(128, 128, 128, 80));
    window.wu_circle(150, 220, 100, Color::rgba(255, 0, 0, 255));
    window.line(0, 0, 200, 200, Color::rgb(255, 0, 0));
    window.line(0, 200, 200, 0, Color::rgb(128, 255, 0));
    // vertical and horizontal line test
    window.line(100, 0, 100, 200, Color::rgb(0, 0, 255));
    window.line(0, 100, 200, 100, Color::rgb(255, 255, 0));
    window.wu_line(100, 220, 400, 250, Color::rgba(255, 0, 0, 255));
    window.line(100, 230, 400, 260, Color::rgba(255, 0, 0, 255));

    // path and bezier curve example draw a cloud
    let mut cloud_path = GraphicsPath::new();
    cloud_path.move_to(170, 80);
    cloud_path.bezier_curve_to(130, 100, 130, 150, 230, 150);
    cloud_path.bezier_curve_to(250, 180, 320, 180, 340, 150);
    cloud_path.bezier_curve_to(420, 150, 420, 120, 390, 100);
    cloud_path.bezier_curve_to(430, 40, 370, 30, 340, 50);
    cloud_path.bezier_curve_to(320, 5, 250, 20, 250, 50);
    cloud_path.bezier_curve_to(200, 5, 150, 20, 170, 80);
    window.draw_path_stroke(cloud_path, Color::rgb(0, 0, 255));

    // path and quadratic curve example draw a balloon
    let mut balloon_path = GraphicsPath::new();
    balloon_path.move_to(75, 25);
    balloon_path.quadratic_curve_to(25, 25, 25, 62);
    balloon_path.quadratic_curve_to(25, 100, 50, 100);
    balloon_path.quadratic_curve_to(50, 120, 30, 125);
    balloon_path.quadratic_curve_to(60, 120, 65, 100);
    balloon_path.quadratic_curve_to(125, 100, 125, 62);
    balloon_path.quadratic_curve_to(125, 25, 75, 25);
    window.draw_path_stroke(balloon_path, Color::rgb(0, 0, 255));

    window.char(200, 200, '═', Color::rgb(0, 0, 0));
    window.char(208, 200, '═', Color::rgb(0, 0, 0));

    // testing for non existent x,y position : does not panic but returns Color(0,0,0,0)
    let _non_existent_pixel = window.getpixel(width as i32 + 10, height as i32 + 10);

    // testing PartialEq for Color
    if Color::rgb(11, 2, 3) == Color::rgba(1, 2, 3, 100) {
        println!("Testing colors: they are the same!")
    } else {
        println!("Testing colors: they are NOT the same!")
    }

    //Draw a transparent rectangle over window content
    // default mode is Blend
    window.rect(250, 200, 80, 80, Color::rgba(100, 100, 100, 100));

    //Draw an opaque rectangle replacing window content
    window.mode().set(Mode::Overwrite); // set window drawing mode to Overwrite from now on
    window.rect(300, 220, 80, 80, Color::rgb(100, 100, 100));

    //Draw a hole in the window replacing alpha channel (Only in Orbital, not in SDL2)
    window.rect(300, 100, 80, 80, Color::rgba(10, 10, 10, 1));

    //Draw a transparent rectangle over window content
    window.mode().set(Mode::Blend); //set mode to Blend fron now on
    window.rect(200, 230, 80, 80, Color::rgba(100, 100, 100, 100));

    //Draw a blured box over window content
    window.box_blur(170, 100, 150, 150, 10);

    //Draw a shadow around a box
    window.box_shadow(170, 100, 150, 150, 0, 0, 20, Color::rgba(0, 0, 0, 255));

    window.sync();

    'events: loop {
        for event in window.events() {
            match event.to_option() {
                EventOption::Quit(_quit_event) => break 'events,
                // EventOption::Mouse(evt) => println!(
                //     "At position {:?} pixel color is : {:?}",
                //     (evt.x, evt.y),
                //     window.getpixel(evt.x, evt.y)
                // ),
                event_option =>  {}//println!("{:?}", event_option),
            }
        }
    }
}
<commit_msg>fix examle<commit_after>extern crate orbclient;

use orbclient::{Color, EventOption, GraphicsPath, Mode, Renderer, Window};

fn main() {
    let (width, height) = orbclient::get_display_size().unwrap();

    let mut window = Window::new(
        (width as i32) / 4,
        (height as i32) / 4,
        width / 2,
        height / 2,
        "TITLE",
    )
    .unwrap();

    let (win_w, win_h) = (width / 2, height / 2);

    // top left -> bottom rigth
    window.linear_gradient(
        0,
        0,
        win_w / 3,
        win_h,
        0,
        0,
        (win_w / 3) as i32,
        (win_h / 2) as i32,
        Color::rgb(128, 128, 128),
        Color::rgb(255, 255, 255),
    );
    // horizontal gradient
    window.linear_gradient(
        (win_w / 3) as i32,
        0,
        win_w / 3,
        win_h,
        (win_w / 3) as i32,
        0,
        (2 * win_w / 3) as i32,
        0,
        Color::rgb(128, 255, 255),
        Color::rgb(255, 255, 255),
    );
    // vertical gradient
    window.linear_gradient(
        (2 * win_w / 3) as i32,
        0,
        win_w / 3,
        win_h,
        (2 * win_w / 3) as i32,
        0,
        (2 * win_w / 3) as i32,
        win_h as i32,
        Color::rgb(0, 128, 0),
        Color::rgb(255, 255, 255),
    );
    window.arc(100, 100, -25, 1 << 0 | 1 << 2, Color::rgb(0, 0, 255));
    window.arc(100, 100, -25, 1 << 1 | 1 << 3, Color::rgb(0, 255, 255));
    window.arc(100, 100, -25, 1 << 4 | 1 << 6, Color::rgb(255, 0, 255));
    window.arc(100, 100, -25, 1 << 5 | 1 << 7, Color::rgb(255, 255, 0));
    window.circle(100, 100, 25, Color::rgb(0, 0, 0));
    window.circle(100, 101, -25, Color::rgb(0, 255, 0));
    window.circle(220, 220, -100, Color::rgba(128, 128, 128, 80));
    window.wu_circle(150, 220, 100, Color::rgba(255, 0, 0, 255));
    window.line(0, 0, 200, 200, Color::rgb(255, 0, 0));
    window.line(0, 200, 200, 0, Color::rgb(128, 255, 0));
    // vertical and horizontal line test
    window.line(100, 0, 100, 200, Color::rgb(0, 0, 255));
    window.line(0, 100, 200, 100, Color::rgb(255, 255, 0));
    window.wu_line(100, 220, 400, 250, Color::rgba(255, 0, 0, 255));
    window.line(100, 230, 400, 260, Color::rgba(255, 0, 0, 255));

    // path and bezier curve example draw a cloud
    let mut cloud_path = GraphicsPath::new();
    cloud_path.move_to(170, 80);
    cloud_path.bezier_curve_to(130, 100, 130, 150, 230, 150);
    cloud_path.bezier_curve_to(250, 180, 320, 180, 340, 150);
    cloud_path.bezier_curve_to(420, 150, 420, 120, 390, 100);
    cloud_path.bezier_curve_to(430, 40, 370, 30, 340, 50);
    cloud_path.bezier_curve_to(320, 5, 250, 20, 250, 50);
    cloud_path.bezier_curve_to(200, 5, 150, 20, 170, 80);
    window.draw_path_stroke(cloud_path, Color::rgb(0, 0, 255));

    // path and quadratic curve example draw a balloon
    let mut balloon_path = GraphicsPath::new();
    balloon_path.move_to(75, 25);
    balloon_path.quadratic_curve_to(25, 25, 25, 62);
    balloon_path.quadratic_curve_to(25, 100, 50, 100);
    balloon_path.quadratic_curve_to(50, 120, 30, 125);
    balloon_path.quadratic_curve_to(60, 120, 65, 100);
    balloon_path.quadratic_curve_to(125, 100, 125, 62);
    balloon_path.quadratic_curve_to(125, 25, 75, 25);
    window.draw_path_stroke(balloon_path, Color::rgb(0, 0, 255));

    window.char(200, 200, '═', Color::rgb(0, 0, 0));
    window.char(208, 200, '═', Color::rgb(0, 0, 0));

    // testing for non existent x,y position : does not panic but returns Color(0,0,0,0)
    let _non_existent_pixel = window.getpixel(width as i32 + 10, height as i32 + 10);

    // testing PartialEq for Color
    if Color::rgb(11, 2, 3) == Color::rgba(1, 2, 3, 100) {
        println!("Testing colors: they are the same!")
    } else {
        println!("Testing colors: they are NOT the same!")
    }

    //Draw a transparent rectangle over window content
    // default mode is Blend
    window.rect(250, 200, 80, 80, Color::rgba(100, 100, 100, 100));

    //Draw an opaque rectangle replacing window content
    window.mode().set(Mode::Overwrite); // set window drawing mode to Overwrite from now on
    window.rect(300, 220, 80, 80, Color::rgb(100, 100, 100));

    //Draw a hole in the window replacing alpha channel (Only in Orbital, not in SDL2)
    window.rect(300, 100, 80, 80, Color::rgba(10, 10, 10, 1));

    //Draw a transparent rectangle over window content
    window.mode().set(Mode::Blend); //set mode to Blend fron now on
    window.rect(200, 230, 80, 80, Color::rgba(100, 100, 100, 100));

    //Draw a blured box over window content
    window.box_blur(170, 100, 150, 150, 10);

    //Draw a shadow around a box
    window.box_shadow(170, 100, 150, 150, 0, 0, 20, Color::rgba(0, 0, 0, 255));

    window.sync();

    'events: loop {
        for event in window.events() {
            match event.to_option() {
                EventOption::Quit(_quit_event) => break 'events,
                EventOption::Mouse(evt) => println!(
                    "At position {:?} pixel color is : {:?}",
                    (evt.x, evt.y),
                    window.getpixel(evt.x, evt.y)
                ),
                event_option =>  println!("{:?}", event_option),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! HTTP Upgrades
//!
//! See [this example][example] showing how upgrades work with both
//! Clients and Servers.
//!
//! [example]: https://github.com/hyperium/hyper/blob/master/examples/upgrades.rs

use std::any::TypeId;
use std::error::Error as StdError;
use std::fmt;
use std::io;
use std::marker::Unpin;

use bytes::Bytes;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::sync::oneshot;
#[cfg(any(feature = "http1", feature = "http2"))]
use tracing::trace;

use crate::common::io::Rewind;
use crate::common::{task, Future, Pin, Poll};

/// An upgraded HTTP connection.
///
/// This type holds a trait object internally of the original IO that
/// was used to speak HTTP before the upgrade. It can be used directly
/// as a `Read` or `Write` for convenience.
///
/// Alternatively, if the exact type is known, this can be deconstructed
/// into its parts.
pub struct Upgraded {
    io: Rewind<Box<dyn Io + Send>>,
}

/// A future for a possible HTTP upgrade.
///
/// If no upgrade was available, or it doesn't succeed, yields an `Error`.
pub struct OnUpgrade {
    rx: Option<oneshot::Receiver<crate::Result<Upgraded>>>,
}

/// The deconstructed parts of an [`Upgraded`](Upgraded) type.
///
/// Includes the original IO type, and a read buffer of bytes that the
/// HTTP state machine may have already read before completing an upgrade.
#[derive(Debug)]
pub struct Parts<T> {
    /// The original IO object used before the upgrade.
    pub io: T,
    /// A buffer of bytes that have been read but not processed as HTTP.
    ///
    /// For instance, if the `Connection` is used for an HTTP upgrade request,
    /// it is possible the server sent back the first bytes of the new protocol
    /// along with the response upgrade.
    ///
    /// You will want to check for any existing bytes if you plan to continue
    /// communicating on the IO object.
    pub read_buf: Bytes,
    _inner: (),
}

/// Gets a pending HTTP upgrade from this message.
pub fn on<T: sealed::CanUpgrade>(msg: T) -> OnUpgrade {
    msg.on_upgrade()
}

#[cfg(any(feature = "http1", feature = "http2"))]
pub(super) struct Pending {
    tx: oneshot::Sender<crate::Result<Upgraded>>,
}

#[cfg(any(feature = "http1", feature = "http2"))]
pub(super) fn pending() -> (Pending, OnUpgrade) {
    let (tx, rx) = oneshot::channel();
    (Pending { tx }, OnUpgrade { rx: Some(rx) })
}

// ===== impl Upgraded =====

impl Upgraded {
    #[cfg(any(feature = "http1", feature = "http2", test))]
    pub(super) fn new<T>(io: T, read_buf: Bytes) -> Self
    where
        T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    {
        Upgraded {
            io: Rewind::new_buffered(Box::new(io), read_buf),
        }
    }

    /// Tries to downcast the internal trait object to the type passed.
    ///
    /// On success, returns the downcasted parts. On error, returns the
    /// `Upgraded` back.
    pub fn downcast<T: AsyncRead + AsyncWrite + Unpin + 'static>(self) -> Result<Parts<T>, Self> {
        let (io, buf) = self.io.into_inner();
        match io.__hyper_downcast() {
            Ok(t) => Ok(Parts {
                io: *t,
                read_buf: buf,
                _inner: (),
            }),
            Err(io) => Err(Upgraded {
                io: Rewind::new_buffered(io, buf),
            }),
        }
    }
}

impl AsyncRead for Upgraded {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_read(cx, buf)
    }
}

impl AsyncWrite for Upgraded {
    fn poll_write(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.io).poll_write(cx, buf)
    }

    fn poll_write_vectored(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        bufs: &[io::IoSlice<'_>],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.io).poll_write_vectored(cx, bufs)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_flush(cx)
    }

    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_shutdown(cx)
    }

    fn is_write_vectored(&self) -> bool {
        self.io.is_write_vectored()
    }
}

impl fmt::Debug for Upgraded {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Upgraded").finish()
    }
}

// ===== impl OnUpgrade =====

impl OnUpgrade {
    pub(super) fn none() -> Self {
        OnUpgrade { rx: None }
    }

    #[cfg(feature = "http1")]
    pub(super) fn is_none(&self) -> bool {
        self.rx.is_none()
    }
}

impl Future for OnUpgrade {
    type Output = Result<Upgraded, crate::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        match self.rx {
            Some(ref mut rx) => Pin::new(rx).poll(cx).map(|res| match res {
                Ok(Ok(upgraded)) => Ok(upgraded),
                Ok(Err(err)) => Err(err),
                Err(_oneshot_canceled) => Err(crate::Error::new_canceled().with(UpgradeExpected)),
            }),
            None => Poll::Ready(Err(crate::Error::new_user_no_upgrade())),
        }
    }
}

impl fmt::Debug for OnUpgrade {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OnUpgrade").finish()
    }
}

// ===== impl Pending =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl Pending {
    pub(super) fn fulfill(self, upgraded: Upgraded) {
        trace!("pending upgrade fulfill");
        let _ = self.tx.send(Ok(upgraded));
    }

    #[cfg(feature = "http1")]
    /// Don't fulfill the pending Upgrade, but instead signal that
    /// upgrades are handled manually.
    pub(super) fn manual(self) {
        trace!("pending upgrade handled manually");
        let _ = self.tx.send(Err(crate::Error::new_user_manual_upgrade()));
    }
}

// ===== impl UpgradeExpected =====

/// Error cause returned when an upgrade was expected but canceled
/// for whatever reason.
///
/// This likely means the actual `Conn` future wasn't polled and upgraded.
#[derive(Debug)]
struct UpgradeExpected;

impl fmt::Display for UpgradeExpected {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("upgrade expected but not completed")
    }
}

impl StdError for UpgradeExpected {}

// ===== impl Io =====

pub(super) trait Io: AsyncRead + AsyncWrite + Unpin + 'static {
    fn __hyper_type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl<T: AsyncRead + AsyncWrite + Unpin + 'static> Io for T {}

impl dyn Io + Send {
    fn __hyper_is<T: Io>(&self) -> bool {
        let t = TypeId::of::<T>();
        self.__hyper_type_id() == t
    }

    fn __hyper_downcast<T: Io>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
        if self.__hyper_is::<T>() {
            // Taken from `std::error::Error::downcast()`.
            unsafe {
                let raw: *mut dyn Io = Box::into_raw(self);
                Ok(Box::from_raw(raw as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

mod sealed {
    use super::OnUpgrade;

    pub trait CanUpgrade {
        fn on_upgrade(self) -> OnUpgrade;
    }

    impl<B> CanUpgrade for http::Request<B> {
        fn on_upgrade(mut self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for &'_ mut http::Request<B> {
        fn on_upgrade(self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for http::Response<B> {
        fn on_upgrade(mut self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for &'_ mut http::Response<B> {
        fn on_upgrade(self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn upgraded_downcast() {
        let upgraded = Upgraded::new(Mock, Bytes::new());

        let upgraded = upgraded.downcast::<std::io::Cursor<Vec<u8>>>().unwrap_err();

        upgraded.downcast::<Mock>().unwrap();
    }

    // TODO: replace with tokio_test::io when it can test write_buf
    struct Mock;

    impl AsyncRead for Mock {
        fn poll_read(
            self: Pin<&mut Self>,
            _cx: &mut task::Context<'_>,
            _buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_read")
        }
    }

    impl AsyncWrite for Mock {
        fn poll_write(
            self: Pin<&mut Self>,
            _: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            // panic!("poll_write shouldn't be called");
            Poll::Ready(Ok(buf.len()))
        }

        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_flush")
        }

        fn poll_shutdown(
            self: Pin<&mut Self>,
            _cx: &mut task::Context<'_>,
        ) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_shutdown")
        }
    }
}
<commit_msg>docs(upgrade): add module documentation for HTTP upgrades<commit_after>//! HTTP Upgrades
//!
//! This module deals with managing [HTTP Upgrades][mdn] in hyper. Since
//! several concepts in HTTP allow for first talking HTTP, and then converting
//! to a different protocol, this module conflates them into a single API.
//! Those include:
//!
//! - HTTP/1.1 Upgrades
//! - HTTP `CONNECT`
//!
//! You are responsible for any other pre-requisites to establish an upgrade,
//! such as sending the appropriate headers, methods, and status codes. You can
//! then use [`on`][] to grab a `Future` which will resolve to the upgraded
//! connection object, or an error if the upgrade fails.
//!
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
//!
//! # Client
//!
//! Sending an HTTP ugprade from the [`client`](super::client) involves setting
//! either the appropriate method, if wanting to `CONNECT`, or headers such as
//! `Upgrade` and `Connection`, on the `http::Request`. Once receiving the
//! `http::Response` back, you must check for the specific information that the
//! upgrade is agreed upon by the server (such as a `101` status code), and then
//! get the `Future` from the `Response`.
//!
//! # Server
//!
//! Receiving upgrade requests in a server requires you to check the relevant
//! headers in a `Request`, and if an upgrade should be done, you then send the
//! corresponding headers in a response. To then wait for hyper to finish the
//! upgrade, you call `on()` with the `Request`, and then can spawn a task
//! awaiting it.
//!
//! # Example
//!
//! See [this example][example] showing how upgrades work with both
//! Clients and Servers.
//!
//! [example]: https://github.com/hyperium/hyper/blob/master/examples/upgrades.rs

use std::any::TypeId;
use std::error::Error as StdError;
use std::fmt;
use std::io;
use std::marker::Unpin;

use bytes::Bytes;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::sync::oneshot;
#[cfg(any(feature = "http1", feature = "http2"))]
use tracing::trace;

use crate::common::io::Rewind;
use crate::common::{task, Future, Pin, Poll};

/// An upgraded HTTP connection.
///
/// This type holds a trait object internally of the original IO that
/// was used to speak HTTP before the upgrade. It can be used directly
/// as a `Read` or `Write` for convenience.
///
/// Alternatively, if the exact type is known, this can be deconstructed
/// into its parts.
pub struct Upgraded {
    io: Rewind<Box<dyn Io + Send>>,
}

/// A future for a possible HTTP upgrade.
///
/// If no upgrade was available, or it doesn't succeed, yields an `Error`.
pub struct OnUpgrade {
    rx: Option<oneshot::Receiver<crate::Result<Upgraded>>>,
}

/// The deconstructed parts of an [`Upgraded`](Upgraded) type.
///
/// Includes the original IO type, and a read buffer of bytes that the
/// HTTP state machine may have already read before completing an upgrade.
#[derive(Debug)]
pub struct Parts<T> {
    /// The original IO object used before the upgrade.
    pub io: T,
    /// A buffer of bytes that have been read but not processed as HTTP.
    ///
    /// For instance, if the `Connection` is used for an HTTP upgrade request,
    /// it is possible the server sent back the first bytes of the new protocol
    /// along with the response upgrade.
    ///
    /// You will want to check for any existing bytes if you plan to continue
    /// communicating on the IO object.
    pub read_buf: Bytes,
    _inner: (),
}

/// Gets a pending HTTP upgrade from this message.
///
/// This can be called on the following types:
///
/// - `http::Request<B>`
/// - `http::Response<B>`
/// - `&mut http::Request<B>`
/// - `&mut http::Response<B>`
pub fn on<T: sealed::CanUpgrade>(msg: T) -> OnUpgrade {
    msg.on_upgrade()
}

#[cfg(any(feature = "http1", feature = "http2"))]
pub(super) struct Pending {
    tx: oneshot::Sender<crate::Result<Upgraded>>,
}

#[cfg(any(feature = "http1", feature = "http2"))]
pub(super) fn pending() -> (Pending, OnUpgrade) {
    let (tx, rx) = oneshot::channel();
    (Pending { tx }, OnUpgrade { rx: Some(rx) })
}

// ===== impl Upgraded =====

impl Upgraded {
    #[cfg(any(feature = "http1", feature = "http2", test))]
    pub(super) fn new<T>(io: T, read_buf: Bytes) -> Self
    where
        T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    {
        Upgraded {
            io: Rewind::new_buffered(Box::new(io), read_buf),
        }
    }

    /// Tries to downcast the internal trait object to the type passed.
    ///
    /// On success, returns the downcasted parts. On error, returns the
    /// `Upgraded` back.
    pub fn downcast<T: AsyncRead + AsyncWrite + Unpin + 'static>(self) -> Result<Parts<T>, Self> {
        let (io, buf) = self.io.into_inner();
        match io.__hyper_downcast() {
            Ok(t) => Ok(Parts {
                io: *t,
                read_buf: buf,
                _inner: (),
            }),
            Err(io) => Err(Upgraded {
                io: Rewind::new_buffered(io, buf),
            }),
        }
    }
}

impl AsyncRead for Upgraded {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_read(cx, buf)
    }
}

impl AsyncWrite for Upgraded {
    fn poll_write(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.io).poll_write(cx, buf)
    }

    fn poll_write_vectored(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
        bufs: &[io::IoSlice<'_>],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.io).poll_write_vectored(cx, bufs)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_flush(cx)
    }

    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
        Pin::new(&mut self.io).poll_shutdown(cx)
    }

    fn is_write_vectored(&self) -> bool {
        self.io.is_write_vectored()
    }
}

impl fmt::Debug for Upgraded {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Upgraded").finish()
    }
}

// ===== impl OnUpgrade =====

impl OnUpgrade {
    pub(super) fn none() -> Self {
        OnUpgrade { rx: None }
    }

    #[cfg(feature = "http1")]
    pub(super) fn is_none(&self) -> bool {
        self.rx.is_none()
    }
}

impl Future for OnUpgrade {
    type Output = Result<Upgraded, crate::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        match self.rx {
            Some(ref mut rx) => Pin::new(rx).poll(cx).map(|res| match res {
                Ok(Ok(upgraded)) => Ok(upgraded),
                Ok(Err(err)) => Err(err),
                Err(_oneshot_canceled) => Err(crate::Error::new_canceled().with(UpgradeExpected)),
            }),
            None => Poll::Ready(Err(crate::Error::new_user_no_upgrade())),
        }
    }
}

impl fmt::Debug for OnUpgrade {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OnUpgrade").finish()
    }
}

// ===== impl Pending =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl Pending {
    pub(super) fn fulfill(self, upgraded: Upgraded) {
        trace!("pending upgrade fulfill");
        let _ = self.tx.send(Ok(upgraded));
    }

    #[cfg(feature = "http1")]
    /// Don't fulfill the pending Upgrade, but instead signal that
    /// upgrades are handled manually.
    pub(super) fn manual(self) {
        trace!("pending upgrade handled manually");
        let _ = self.tx.send(Err(crate::Error::new_user_manual_upgrade()));
    }
}

// ===== impl UpgradeExpected =====

/// Error cause returned when an upgrade was expected but canceled
/// for whatever reason.
///
/// This likely means the actual `Conn` future wasn't polled and upgraded.
#[derive(Debug)]
struct UpgradeExpected;

impl fmt::Display for UpgradeExpected {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("upgrade expected but not completed")
    }
}

impl StdError for UpgradeExpected {}

// ===== impl Io =====

pub(super) trait Io: AsyncRead + AsyncWrite + Unpin + 'static {
    fn __hyper_type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl<T: AsyncRead + AsyncWrite + Unpin + 'static> Io for T {}

impl dyn Io + Send {
    fn __hyper_is<T: Io>(&self) -> bool {
        let t = TypeId::of::<T>();
        self.__hyper_type_id() == t
    }

    fn __hyper_downcast<T: Io>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
        if self.__hyper_is::<T>() {
            // Taken from `std::error::Error::downcast()`.
            unsafe {
                let raw: *mut dyn Io = Box::into_raw(self);
                Ok(Box::from_raw(raw as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

mod sealed {
    use super::OnUpgrade;

    pub trait CanUpgrade {
        fn on_upgrade(self) -> OnUpgrade;
    }

    impl<B> CanUpgrade for http::Request<B> {
        fn on_upgrade(mut self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for &'_ mut http::Request<B> {
        fn on_upgrade(self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for http::Response<B> {
        fn on_upgrade(mut self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }

    impl<B> CanUpgrade for &'_ mut http::Response<B> {
        fn on_upgrade(self) -> OnUpgrade {
            self.extensions_mut()
                .remove::<OnUpgrade>()
                .unwrap_or_else(OnUpgrade::none)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn upgraded_downcast() {
        let upgraded = Upgraded::new(Mock, Bytes::new());

        let upgraded = upgraded.downcast::<std::io::Cursor<Vec<u8>>>().unwrap_err();

        upgraded.downcast::<Mock>().unwrap();
    }

    // TODO: replace with tokio_test::io when it can test write_buf
    struct Mock;

    impl AsyncRead for Mock {
        fn poll_read(
            self: Pin<&mut Self>,
            _cx: &mut task::Context<'_>,
            _buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_read")
        }
    }

    impl AsyncWrite for Mock {
        fn poll_write(
            self: Pin<&mut Self>,
            _: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            // panic!("poll_write shouldn't be called");
            Poll::Ready(Ok(buf.len()))
        }

        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_flush")
        }

        fn poll_shutdown(
            self: Pin<&mut Self>,
            _cx: &mut task::Context<'_>,
        ) -> Poll<io::Result<()>> {
            unreachable!("Mock::poll_shutdown")
        }
    }
}
<|endoftext|>


<commit_before>
extern crate ntpclient;
extern crate time;

use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
use time::{Timespec, at, Duration, precise_time_ns};

const BILLION: u64 = 1_000_000_000;

// NOTE: obsolete when Rust starts to support UDP receive timeout
struct NtpFetcher {
    server: String,
    last_sync: Arc<Mutex<(Timespec, u64)>>,
    poll: Duration,
    last_poll: u64,
}

impl NtpFetcher {
    fn new(server: String, ntp_poll: Duration) -> NtpFetcher {
        let mut ntp = NtpFetcher {
            server: server,
            last_sync: Arc::new(Mutex::new((Timespec::new(0,0), 0))),
            poll: ntp_poll,
            last_poll: 0,
        };

        ntp.consider_poll_ntp();
        ntp
    }

    fn consider_poll_ntp(&mut self) {
        if let Ok(ref lock) = self.last_sync.lock() {
            let (_, ref_time) = **lock;
            let poll_interval = if ref_time == 0 {
                // when never NTP timestamp was received, try again after 10 minutes
                Duration::minutes(10)
            } else {
                self.poll
            };

            let curr = precise_time_ns();
            let must_poll = (self.last_poll == 0) ||
                (((curr - self.last_poll) / BILLION) >= poll_interval.num_seconds() as u64);

            if must_poll {
                self.last_poll = curr;
                let sync = self.last_sync.clone();
                let server = self.server.clone();

                thread::spawn(move || {
                    println!("receiving timestamp");
                    if let Ok(ts) = ntpclient::retrieve_ntp_timestamp(&server[..]) {
                        if let Ok(ref mut lock) = sync.lock() {
                            **lock = (ts, precise_time_ns());
                        }
                    }
                });
            }
        }
    }

    fn get_timespec(&mut self) -> Option<Timespec> {
        self.consider_poll_ntp();
        match self.last_sync.lock() {
            Ok(ref lock) => {
                let (sync_ts, ref_time) = **lock;

                match ref_time {
                    0 => None,
                    _ => {
                        let ns = precise_time_ns() - ref_time;
                        Some(sync_ts + Duration::nanoseconds(ns as i64))
                    }
                }
            },
            Err(_) => None,
        }
    }
}

struct Ticker<C> {
    rx: Receiver<(C, Option<Timespec>)>,
    tx: Sender<(C, Option<Timespec>)>,
    joiner: thread::JoinHandle<()>,
    leave_guard: Arc<(Mutex<bool>, Condvar)>,
}

impl<C> Ticker<C> where C: Send + Copy + 'static {
    fn spawn(server: &str, tick_interval: Duration, ntp_poll: Duration, event: C) -> Ticker<C> {
        let (tx, rx) = channel();
        let leave_guard = Arc::new((Mutex::new(true), Condvar::new()));
        let waiter = leave_guard.clone();
        let cloned_tx = tx.clone();
        let server = server.into();

        let joiner = thread::spawn(move || {
            let mut ntp = NtpFetcher::new(server, ntp_poll);
            let &(ref lock, ref cvar) = &*waiter;
            let mut leaver = lock.lock().ok().expect("BUG: mutex cannot claimed inside thread");

            // this loop sends the NTP synchronized timestamp to receiving end of the channel
            while *leaver {
                let (new_leaver, _) =
                    cvar.wait_timeout_ms(leaver,
                                         tick_interval.num_milliseconds() as u32).ok().expect(
                                             "BUG: unexpected error during wait");

                leaver = new_leaver;

                if *leaver {
                    if let Some(ts) = ntp.get_timespec() {
                        tx.send((event, Some(ts))).ok().expect("BUG: cannot send timestamp");
                    }
                }
            }
        });

        Ticker {
            rx: rx,
            tx: cloned_tx,
            joiner: joiner,
            leave_guard: leave_guard,
        }
    }

    fn stop_ticker(self) {
        let &(ref lock, ref cvar) = &*(self.leave_guard);
        let mut leaver = lock.lock().ok().expect("BUG: cannot claim mutex during stop_ticker");
        *leaver = false;
        drop(leaver);
        cvar.notify_all();
        let _ = self.joiner.join();
    }

    fn get_transmitter(&self) -> Sender<(C, Option<Timespec>)> {
        self.tx.clone()
    }
}

#[derive(Copy, Clone)]
enum Dummy {
    Dummy
}

fn main() {
    let ticker = Ticker::spawn("nl.pool.ntp.org", Duration::seconds(1), Duration::days(1), Dummy::Dummy);
    let _ = ticker.get_transmitter(); // suppress warning

    let mut teller = 0; // XXX

    loop {
        let (_, timestamp) = ticker.rx.recv().unwrap();

        if let Some(timestamp) = timestamp {
            println!("{}", at(timestamp).asctime());
        }

        teller = teller + 1;
        if teller >= 5 {
            ticker.stop_ticker();
            break;
        }
    }
}
<commit_msg>ticker: recv function moved to ticker struct<commit_after>
extern crate ntpclient;
extern crate time;

use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
use time::{Timespec, at, Duration, precise_time_ns};

const BILLION: u64 = 1_000_000_000;

// NOTE: obsolete when Rust starts to support UDP receive timeout
struct NtpFetcher {
    server: String,
    last_sync: Arc<Mutex<(Timespec, u64)>>,
    poll: Duration,
    last_poll: u64,
}

impl NtpFetcher {
    fn new(server: String, ntp_poll: Duration) -> NtpFetcher {
        let mut ntp = NtpFetcher {
            server: server,
            last_sync: Arc::new(Mutex::new((Timespec::new(0,0), 0))),
            poll: ntp_poll,
            last_poll: 0,
        };

        ntp.consider_poll_ntp();
        ntp
    }

    fn consider_poll_ntp(&mut self) {
        if let Ok(ref lock) = self.last_sync.lock() {
            let (_, ref_time) = **lock;
            let poll_interval = if ref_time == 0 {
                // when never NTP timestamp was received, try again after 10 minutes
                Duration::minutes(10)
            } else {
                self.poll
            };

            let curr = precise_time_ns();
            let must_poll = (self.last_poll == 0) ||
                (((curr - self.last_poll) / BILLION) >= poll_interval.num_seconds() as u64);

            if must_poll {
                self.last_poll = curr;
                let sync = self.last_sync.clone();
                let server = self.server.clone();

                thread::spawn(move || {
                    println!("receiving timestamp");
                    if let Ok(ts) = ntpclient::retrieve_ntp_timestamp(&server[..]) {
                        if let Ok(ref mut lock) = sync.lock() {
                            **lock = (ts, precise_time_ns());
                        }
                    }
                });
            }
        }
    }

    fn get_timespec(&mut self) -> Option<Timespec> {
        self.consider_poll_ntp();
        match self.last_sync.lock() {
            Ok(ref lock) => {
                let (sync_ts, ref_time) = **lock;

                match ref_time {
                    0 => None,
                    _ => {
                        let ns = precise_time_ns() - ref_time;
                        Some(sync_ts + Duration::nanoseconds(ns as i64))
                    }
                }
            },
            Err(_) => None,
        }
    }
}

struct Ticker<C> {
    rx: Receiver<(C, Option<Timespec>)>,
    tx: Sender<(C, Option<Timespec>)>,
    joiner: thread::JoinHandle<()>,
    leave_guard: Arc<(Mutex<bool>, Condvar)>,
}

impl<C> Ticker<C> where C: Send + Copy + 'static {
    fn spawn(server: &str, tick_interval: Duration, ntp_poll: Duration, event: C) -> Ticker<C> {
        let (tx, rx) = channel();
        let leave_guard = Arc::new((Mutex::new(true), Condvar::new()));
        let waiter = leave_guard.clone();
        let cloned_tx = tx.clone();
        let server = server.into();

        let joiner = thread::spawn(move || {
            let mut ntp = NtpFetcher::new(server, ntp_poll);
            let &(ref lock, ref cvar) = &*waiter;
            let mut leaver = lock.lock().ok().expect("BUG: mutex cannot claimed inside thread");

            // this loop sends the NTP synchronized timestamp to receiving end of the channel
            while *leaver {
                let (new_leaver, _) =
                    cvar.wait_timeout_ms(leaver,
                                         tick_interval.num_milliseconds() as u32).ok().expect(
                                             "BUG: unexpected error during wait");

                leaver = new_leaver;

                if *leaver {
                    if let Some(ts) = ntp.get_timespec() {
                        tx.send((event, Some(ts))).ok().expect("BUG: cannot send timestamp");
                    }
                }
            }
        });

        Ticker {
            rx: rx,
            tx: cloned_tx,
            joiner: joiner,
            leave_guard: leave_guard,
        }
    }

    fn stop_ticker(self) {
        let &(ref lock, ref cvar) = &*(self.leave_guard);
        let mut leaver = lock.lock().ok().expect("BUG: cannot claim mutex during stop_ticker");
        *leaver = false;
        drop(leaver);
        cvar.notify_all();
        let _ = self.joiner.join();
    }

    fn get_transmitter(&self) -> Sender<(C, Option<Timespec>)> {
        self.tx.clone()
    }

    fn recv(&self) -> (C, Option<Timespec>) {
        self.rx.recv().ok().expect("BUG: ticker channel has no senders")
    }
}

#[derive(Copy, Clone)]
enum Dummy {
    Dummy
}

fn main() {
    let ticker = Ticker::spawn("nl.pool.ntp.org", Duration::seconds(1), Duration::days(1), Dummy::Dummy);
    let _ = ticker.get_transmitter(); // suppress warning

    let mut teller = 0; // XXX

    loop {
        let (_, timestamp) = ticker.recv();

        if let Some(timestamp) = timestamp {
            println!("{}", at(timestamp).asctime());
        }

        teller = teller + 1;
        if teller >= 5 {
            ticker.stop_ticker();
            break;
        }
    }
}
<|endoftext|>