<commit_before>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::Spanned;
use utils::{span_lint_and_sugg, snippet};
use std::ops::Deref;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to assign '()' to valiable. Instead,
///   Unit is what a block evaluates to when it returns nothing. This is typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if is_unit_expr(right){
                span_lint_and_sugg(
                    cx,
                    UNIT_EXPR,
                    right.span,
                    "trailing semicolons can be tricky",
                    "remove the last semicolon",
                    "TODO".to_owned()
                )
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for ref arg in args{
                if is_unit_expr(arg){
                    span_lint_and_sugg(
                        cx,
                        UNIT_EXPR,
                        arg.span,
                        "trailing semicolons can be tricky",
                        "remove the last semicolon",
                        "TODO".to_owned()
                    )
                }
            }
        }
        if let ExprKind::Call( _, ref args) = expr.node{
            for ref arg in args{
                if is_unit_expr(arg){
                    span_lint_and_sugg(
                        cx,
                        UNIT_EXPR,
                        arg.span,
                        "trailing semicolons can be tricky",
                        "remove the last semicolon",
                        "TODO".to_owned()
                    )
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node{
            if local.pat.node == PatKind::Wild {return;}
            if let Some(ref expr) = local.init{
                if is_unit_expr(expr){
                    span_lint_and_sugg(
                        cx,
                        UNIT_EXPR,
                        local.span,
                        "trailing semicolons can be tricky",
                        "remove the last semicolon",
                        "TODO".to_owned()
                    )
                }
            }
            }
    }
}

fn is_unit_expr(expr: &Expr)->bool{
    match expr.node{
         ExprKind::Block(ref block) => {
             return check_last_stmt_in_block(block);
        },
        ExprKind::If(_, ref then, ref else_)=>{
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_{
                return check_then && is_unit_expr(else_.deref());
            }
            return check_then;
        }
        _ => return false,
    }
}

fn check_last_stmt_in_block(block: &Block)->bool{
    let ref final_stmt = &block.stmts[block.stmts.len()-1];
        if let StmtKind::Expr(_) = final_stmt.node{
                return false;
            }
            else{
                return true;
            }
}<commit_msg>Improved spans for lints and support match expressions<commit_after>use rustc::lint::*;
use syntax::ast::*;
use std::ops::Deref;
use syntax::ext::quote::rt::Span;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to assign '()' to valiable. Instead,
///   Unit is what a block evaluates to when it returns nothing. This is typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if let Some(span) = is_unit_expr(right){
                    cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon");
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for ref arg in args{
                if let Some(span) = is_unit_expr(arg){
                    cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon");
                }
            }
        }
        if let ExprKind::Call( _, ref args) = expr.node{
            for ref arg in args{
                if let Some(span) = is_unit_expr(arg){
                       cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon");
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node{
            if local.pat.node == PatKind::Wild {return;}
            if let Some(ref expr) = local.init{
                if let Some(span) = is_unit_expr(expr){
                    cx.span_lint(UNIT_EXPR, span, "Consider removing the trailing semicolon");
            }
    }
}
}
}
fn is_unit_expr(expr: &Expr)->Option<Span>{
    match expr.node{
         ExprKind::Block(ref block) => {
             if check_last_stmt_in_block(block){
                 return Some(block.stmts[block.stmts.len()-1].span.clone());
             } else{
                 return None;
             }
        },
        ExprKind::If(_, ref then, ref else_)=>{
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_{
                let check_else = is_unit_expr(*else_);
                if let Some(ref expr_else) = check_else{
                    return Some(expr_else.clone());
                }else{
                    return Some(expr.span.clone());
                }
            }
            if check_then {
                return Some(expr.span.clone());

            } else{
                return Some(expr.span.clone());
            }
        },
        ExprKind::Match(ref _pattern, ref arms ) =>{
            for ref arm in arms{
                if let Some(expr) = is_unit_expr(&arm.body){
                    return Some(expr);
                }
            }
            return None;
        }
        _ => return None,
    }
}

fn check_last_stmt_in_block(block: &Block)->bool{
    let ref final_stmt = &block.stmts[block.stmts.len()-1];
        if let StmtKind::Expr(_) = final_stmt.node{
                return false;
            }
            else{
              return true;
            }
}<|endoftext|>


<commit_before>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
use std::sync::Arc;
use std::cell::RefCell;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T> (self: &mut Self, Name,
                 body:Box<Invoke<&mut Self, T> + 'static>) -> T ;

    fn put<T:Eq> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq> (self:&mut Self, MutArt<T>) ;

    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Arc<Lineage>,Arc<Lineage>),
    ForkL(Arc<Lineage>),
    ForkR(Arc<Lineage>),
    String(String),
    U64(u64),
    Arc(Arc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Arc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Arc<Lineage>,
    path : Arc<Path>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Node(Arc<Name>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

struct PureNode<T> {
    name : Name,
    val : T,
}

struct MutNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    val : RefCell<T>,
}

trait Body<T> {
    fn run (self:&Self, st:&mut AdaptonState) -> T ;
}

struct ComputeNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    body : Box<Body<T> + 'static>, // Trait in Type: Need lifetime.
    val  : RefCell<Option<T>>,
}

struct DemPrec {
    name : Name,
}

struct DemSucc {
    name : Name,
    dirty : RefCell<bool>
}

pub struct AdaptonState {
    memo_table : HashMap<ArtId, *mut ()>, // memo table
    curr_path : Arc<Path>, // current_namespace
    curr_name : Arc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Arc::new(Path::Empty);
        let root = Arc::new(Name{hash:0, lineage:Arc::new(Lineage::Root), path:empty.clone()});
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Arc::new(p), path:self.curr_path.clone() }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Arc::new(Lineage::ForkL(nm.lineage.clone())),
                path:self.curr_path.clone() } ,
          Name{ hash:h2,
                lineage:Arc::new(Lineage::ForkR(nm.lineage)),
                path:self.curr_path.clone() } )
    }
    fn ns<T> (self: &mut Self, nm:Name, body:Box<Invoke<&mut Self,T>+'static>) -> T {
        let path_body = Arc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body.invoke(self) ;
        // TODO: Overcome borrow-checker error here: XXX
        //let path_body = replace(&mut self.curr_path, path_pre) ;
        //drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        panic!("")
    }
    fn set<T:Eq> (self:&mut Self, cell:MutArt<T>) {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Node(nm) => panic!(""),
        }
    }
}

pub fn main () {

}
<commit_msg>fixed borrow-checker obstacle, wrt thrreading &mut AdaptonState around<commit_after>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
use std::sync::Arc;
use std::cell::RefCell;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name,
                 body:F) -> T where F:FnOnce(&mut Self) -> T;

    fn put<T:Eq> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq> (self:&mut Self, MutArt<T>) ;

    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Arc<Lineage>,Arc<Lineage>),
    ForkL(Arc<Lineage>),
    ForkR(Arc<Lineage>),
    String(String),
    U64(u64),
    Arc(Arc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Arc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Arc<Lineage>,
    path : Arc<Path>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Node(Arc<Name>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

struct PureNode<T> {
    name : Name,
    val : T,
}

struct MutNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    val : RefCell<T>,
}

trait Body<T> {
    fn run (self:&Self, st:&mut AdaptonState) -> T ;
}

struct ComputeNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    body : Box<Body<T> + 'static>, // Trait in Type: Need lifetime.
    val  : RefCell<Option<T>>,
}

struct DemPrec {
    name : Name,
}

struct DemSucc {
    name : Name,
    dirty : RefCell<bool>
}

pub struct AdaptonState {
    memo_table : HashMap<ArtId, *mut ()>, // memo table
    curr_path : Arc<Path>, // current_namespace
    curr_name : Arc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Arc::new(Path::Empty);
        let root = Arc::new(Name{hash:0, lineage:Arc::new(Lineage::Root), path:empty.clone()});
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Arc::new(p), path:self.curr_path.clone() }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Arc::new(Lineage::ForkL(nm.lineage.clone())),
                path:self.curr_path.clone() } ,
          Name{ hash:h2,
                lineage:Arc::new(Lineage::ForkR(nm.lineage)),
                path:self.curr_path.clone() } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Arc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        panic!("")
    }
    fn set<T:Eq> (self:&mut Self, cell:MutArt<T>) {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Node(nm) => panic!(""),
        }
    }
}

pub fn main () {

}
<|endoftext|>


<commit_before>use cairo;
use cairo::MatrixTrait;

pub fn intersect(r1: &cairo::Rectangle, r2: &cairo::Rectangle) -> cairo::Rectangle {
    let (x1, y1, x2, y2) = (
        r1.x.max(r2.x),
        r1.y.max(r2.y),
        (r1.x + r1.width).min(r2.x + r2.width),
        (r1.y + r1.height).min(r2.y + r2.height),
    );

    cairo::Rectangle {
        x: x1,
        y: y1,
        width: x2 - x1,
        height: y2 - y1,
    }
}

pub fn union(r1: &cairo::Rectangle, r2: &cairo::Rectangle) -> cairo::Rectangle {
    let (x1, y1, x2, y2) = (
        r1.x.min(r2.x),
        r1.y.min(r2.y),
        (r1.x + r1.width).max(r2.x + r2.width),
        (r1.y + r1.height).max(r2.y + r2.height),
    );

    cairo::Rectangle {
        x: x1,
        y: y1,
        width: x2 - x1,
        height: y2 - y1,
    }
}

pub fn transform(affine: &cairo::Matrix, rect: &cairo::Rectangle) -> cairo::Rectangle {
    let points = vec![
        affine.transform_point(rect.x, rect.y),
        affine.transform_point(rect.x + rect.width, rect.y),
        affine.transform_point(rect.x, rect.y + rect.height),
        affine.transform_point(rect.x + rect.width, rect.y + rect.height),
    ];

    let (mut xmin, mut ymin, mut xmax, mut ymax) = {
        let (x, y) = points[0];

        (x, y, x, y)
    };

    for i in 1..4 {
        let (x, y) = points[i];

        if x < xmin {
            xmin = x;
        }

        if x > xmax {
            xmax = x;
        }

        if y < ymin {
            ymin = y;
        }

        if y > ymax {
            ymax = y;
        }
    }

    cairo::Rectangle {
        x: xmin,
        y: ymin,
        width: xmax - xmin,
        height: ymax - ymin,
    }
}

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

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = intersect(&r1, &r2);
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = union(&r1, &r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = transform(&m, &r);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = transform(&m, &r);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }
}
<commit_msg>rect: handle intersection of disjoint rects<commit_after>use cairo;
use cairo::MatrixTrait;

#[allow(dead_code)]
pub fn is_empty(r: &cairo::Rectangle) -> bool {
    r.width == 0.0 || r.height == 0.0
}

pub fn intersect(r1: &cairo::Rectangle, r2: &cairo::Rectangle) -> cairo::Rectangle {
    let (x1, y1, x2, y2) = (
        r1.x.max(r2.x),
        r1.y.max(r2.y),
        (r1.x + r1.width).min(r2.x + r2.width),
        (r1.y + r1.height).min(r2.y + r2.height),
    );

    if x2 > x1 && y2 > y1 {
        cairo::Rectangle {
            x: x1,
            y: y1,
            width: x2 - x1,
            height: y2 - y1,
        }
    } else {
        cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 0.0,
            height: 0.0,
        }
    }
}

pub fn union(r1: &cairo::Rectangle, r2: &cairo::Rectangle) -> cairo::Rectangle {
    let (x1, y1, x2, y2) = (
        r1.x.min(r2.x),
        r1.y.min(r2.y),
        (r1.x + r1.width).max(r2.x + r2.width),
        (r1.y + r1.height).max(r2.y + r2.height),
    );

    cairo::Rectangle {
        x: x1,
        y: y1,
        width: x2 - x1,
        height: y2 - y1,
    }
}

pub fn transform(affine: &cairo::Matrix, rect: &cairo::Rectangle) -> cairo::Rectangle {
    let points = vec![
        affine.transform_point(rect.x, rect.y),
        affine.transform_point(rect.x + rect.width, rect.y),
        affine.transform_point(rect.x, rect.y + rect.height),
        affine.transform_point(rect.x + rect.width, rect.y + rect.height),
    ];

    let (mut xmin, mut ymin, mut xmax, mut ymax) = {
        let (x, y) = points[0];

        (x, y, x, y)
    };

    for i in 1..4 {
        let (x, y) = points[i];

        if x < xmin {
            xmin = x;
        }

        if x > xmax {
            xmax = x;
        }

        if y < ymin {
            ymin = y;
        }

        if y > ymax {
            ymax = y;
        }
    }

    cairo::Rectangle {
        x: xmin,
        y: ymin,
        width: xmax - xmin,
        height: ymax - ymin,
    }
}

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

    #[test]
    fn empty_rect() {
        let empty = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 0.0,
            height: 0.0,
        };
        let not_empty = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        assert!(is_empty(&empty));
        assert!(!is_empty(&not_empty));
    }

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };
        let r3 = cairo::Rectangle {
            x: 10.0,
            y: 10.0,
            width: 3.14,
            height: 3.14,
        };

        let r = intersect(&r1, &r2);
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);

        let r = intersect(&r1, &r3);
        assert!(is_empty(&r));
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = union(&r1, &r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = transform(&m, &r);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = transform(&m, &r);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::convert::Into;

use crate::common::CodecList;
use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;
use crate::data::params::CodecParams;
use crate::data::value::Value;

use crate::error::*;

/// Used to interact with an encoder.
pub trait Encoder: Send {
    /// Returns the extra data added by an encoder to a codec.
    fn get_extradata(&self) -> Option<Vec<u8>>;
    /// Sends to the encoder a frame to be encoded.
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    /// Returns an encoded packet.
    fn receive_packet(&mut self) -> Result<Packet>;
    /// Tells encoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;

    /// Configures the encoder.
    fn configure(&mut self) -> Result<()>;
    /// Sets an encoder option.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
    //
    /// Sets the parameters associated to a determined codec.
    fn set_params(&mut self, params: &CodecParams) -> Result<()>;
    /// Gets the parameters associated to a determined codec.
    fn get_params(&self) -> Result<CodecParams>;
}

/// Auxiliary structure to encapsulate an encoder object and
/// its additional data.
pub struct Context<E: Encoder> {
    enc: E,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl<E: Encoder> Context<E> {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative encoder, and encapsulates it into a new `Context`.
    pub fn by_name<T: Descriptor<OutputEncoder = E> + ?Sized>(
        codecs: &Codecs<T>,
        name: &str,
    ) -> Option<Self> {
        codecs.by_name(name).map(|builder| Context {
            enc: builder.create(),
        })
    }

    /// Configures the encoder.
    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    /// Sets the parameters associated to a determined codec.
    pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
        self.enc.set_params(params)
    }

    /// Gets the parameters associated to a determined codec.
    pub fn get_params(&self) -> Result<CodecParams> {
        self.enc.get_params()
    }

    /// Sets an encoder option.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    /// Returns the extra data added by an encoder to a codec.
    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    /// Sends to the encoder a frame to be encoded.
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    /// Returns an encoded packet.
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    /// Tells encoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.enc.flush()
    }
}

/// Codec descriptor.
///
/// Contains information on a codec and its own encoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Used to get the descriptor of a codec and create its own encoder.
pub trait Descriptor {
    type OutputEncoder: Encoder;

    /// Creates a new encoder for the requested codec.
    fn create(&self) -> Self::OutputEncoder;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
    list: HashMap<&'static str, Vec<&'static T>>,
}

impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
    type D = T;

    fn new() -> Self {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        pub struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            type OutputEncoder = Enc;

            fn create(&self) -> Self::OutputEncoder {
                Enc {
                    state: 0,
                    w: None,
                    h: None,
                    format: None,
                }
            }

            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(Error::ConfigurationIncomplete)
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(Error::Unsupported(format!("{} key", key))),
                }

                Ok(())
            }

            fn set_params(&mut self, params: &CodecParams) -> Result<()> {
                use crate::data::params::*;

                if let Some(MediaKind::Video(ref info)) = params.kind {
                    self.w = Some(info.width);
                    self.h = Some(info.height);
                    self.format = info.format.clone();
                }
                Ok(())
            }

            fn get_params(&self) -> Result<CodecParams> {
                use crate::data::params::*;

                if self.w.is_none() || self.w.is_none() || self.format.is_none() {
                    return Err(Error::ConfigurationIncomplete);
                }

                Ok(CodecParams {
                    kind: Some(MediaKind::Video(VideoInfo {
                        height: self.w.unwrap(),
                        width: self.h.unwrap(),
                        format: self.format.clone(),
                    })),
                    codec_id: Some("dummy".to_owned()),
                    extradata: self.get_extradata(),
                    bit_rate: 0,
                    convergence_window: 0,
                    delay: 0,
                })
            }

            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            },
        };
    }

    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<commit_msg>codec: Add an API to get the underlying encoder<commit_after>use std::collections::HashMap;
use std::convert::Into;

use crate::common::CodecList;
use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;
use crate::data::params::CodecParams;
use crate::data::value::Value;

use crate::error::*;

/// Used to interact with an encoder.
pub trait Encoder: Send {
    /// Returns the extra data added by an encoder to a codec.
    fn get_extradata(&self) -> Option<Vec<u8>>;
    /// Sends to the encoder a frame to be encoded.
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    /// Returns an encoded packet.
    fn receive_packet(&mut self) -> Result<Packet>;
    /// Tells encoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;

    /// Configures the encoder.
    fn configure(&mut self) -> Result<()>;
    /// Sets an encoder option.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
    //
    /// Sets the parameters associated to a determined codec.
    fn set_params(&mut self, params: &CodecParams) -> Result<()>;
    /// Gets the parameters associated to a determined codec.
    fn get_params(&self) -> Result<CodecParams>;
}

/// Auxiliary structure to encapsulate an encoder object and
/// its additional data.
pub struct Context<E: Encoder> {
    enc: E,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl<E: Encoder> Context<E> {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative encoder, and encapsulates it into a new `Context`.
    pub fn by_name<T: Descriptor<OutputEncoder = E> + ?Sized>(
        codecs: &Codecs<T>,
        name: &str,
    ) -> Option<Self> {
        codecs.by_name(name).map(|builder| Context {
            enc: builder.create(),
        })
    }

    /// Configures the encoder.
    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    /// Sets the parameters associated to a determined codec.
    pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
        self.enc.set_params(params)
    }

    /// Gets the parameters associated to a determined codec.
    pub fn get_params(&self) -> Result<CodecParams> {
        self.enc.get_params()
    }

    /// Sets an encoder option.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    /// Returns the extra data added by an encoder to a codec.
    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    /// Sends to the encoder a frame to be encoded.
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    /// Returns an encoded packet.
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    /// Tells encoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.enc.flush()
    }

    /// Returns the underlying encoder.
    pub fn encoder(&self) -> &E {
        &self.enc
    }
}

/// Codec descriptor.
///
/// Contains information on a codec and its own encoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Used to get the descriptor of a codec and create its own encoder.
pub trait Descriptor {
    type OutputEncoder: Encoder;

    /// Creates a new encoder for the requested codec.
    fn create(&self) -> Self::OutputEncoder;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
    list: HashMap<&'static str, Vec<&'static T>>,
}

impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
    type D = T;

    fn new() -> Self {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        pub struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            type OutputEncoder = Enc;

            fn create(&self) -> Self::OutputEncoder {
                Enc {
                    state: 0,
                    w: None,
                    h: None,
                    format: None,
                }
            }

            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(Error::ConfigurationIncomplete)
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(Error::Unsupported(format!("{} key", key))),
                }

                Ok(())
            }

            fn set_params(&mut self, params: &CodecParams) -> Result<()> {
                use crate::data::params::*;

                if let Some(MediaKind::Video(ref info)) = params.kind {
                    self.w = Some(info.width);
                    self.h = Some(info.height);
                    self.format = info.format.clone();
                }
                Ok(())
            }

            fn get_params(&self) -> Result<CodecParams> {
                use crate::data::params::*;

                if self.w.is_none() || self.w.is_none() || self.format.is_none() {
                    return Err(Error::ConfigurationIncomplete);
                }

                Ok(CodecParams {
                    kind: Some(MediaKind::Video(VideoInfo {
                        height: self.w.unwrap(),
                        width: self.h.unwrap(),
                        format: self.format.clone(),
                    })),
                    codec_id: Some("dummy".to_owned()),
                    extradata: self.get_extradata(),
                    bit_rate: 0,
                    convergence_window: 0,
                    delay: 0,
                })
            }

            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            },
        };
    }

    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<|endoftext|>


<commit_before>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use std::thread;
use std::sync::mpsc::{sync_channel, SyncSender};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use serde_json;
use iron::prelude::*;
use router::Router;
use websocket::{Server as WsServer, Message as WsMessage};

use super::Debugger;
use memory::Memory;
use cpu::registers::Registers;
use self::debugger_command::{DebuggerCommand, BreakReason};
use self::http_handlers::{ToggleBreakpointHandler, ContinueHandler, StepHandler};
use self::breakpoint_map::BreakpointMap;
use self::cpu_snapshot::CpuSnapshot;

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

pub struct HttpDebugger {
    ws_sender: Option<SyncSender<DebuggerCommand>>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    is_stepping: Arc<AtomicBool>,
    prg_offset: u16,
    last_pc: u16,
}

impl HttpDebugger {
    pub fn new(prg_offset: u16) -> Self {
        HttpDebugger {
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            ws_sender: None,
            cpu_thread_handle: thread::current(),
            is_stepping: Arc::new(AtomicBool::new(true)),
            last_pc: 0,
            prg_offset: prg_offset,
        }
    }

    pub fn start(&mut self) -> Result<(), String> {
        if self.ws_sender.is_some() {
            panic!("Start already called.");
        }

        self.start_http_server_thread()?;
        self.start_websocket_thread()?;
        Ok(())
    }

    fn start_websocket_thread(&mut self) -> Result<(), String> {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let (debugger_tx, client_rx) = sync_channel::<DebuggerCommand>(0);
        self.ws_sender = Some(debugger_tx);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).map_err(|e| e.to_string())?;
        info!("Waiting for debugger to attach");
        let connection = ws_server.accept();
        info!("Debugger attached!");
        thread::spawn(move || {
            let request = connection.unwrap().read_request().unwrap();
            request.validate().unwrap();
            let response = request.accept();
            let mut sender = response.send().unwrap();

            while let Ok(debugger_msg) = client_rx.recv() {
                let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                    .unwrap());

                if sender.send_message(&message).is_err() {
                    break;
                }
            }

            info!("Websocket thread is terminating!")
        });

        Ok(())
    }

    fn start_http_server_thread(&self) -> Result<(), String> {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let is_stepping = self.is_stepping.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread.clone(), is_stepping),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints.clone()),
                       "toggle_breakpoint");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });

        Ok(())
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.is_stepping.compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }
}

impl Default for HttpDebugger {
    fn default() -> Self {
        Self::new(0)
    }
}

impl<Mem: Memory> Debugger<Mem> for HttpDebugger {
    fn on_step(&mut self, mem: &Mem, registers: &Registers, cycles: u64) {
        if let Some(ref sender) = self.ws_sender {
            let is_stepping = self.is_stepping.load(Ordering::Relaxed);
            if is_stepping || self.at_breakpoint(registers.pc) || self.last_pc == registers.pc {
                {
                    let snapshot = CpuSnapshot::new(mem.clone(),
                                                    registers.clone(),
                                                    cycles,
                                                    self.prg_offset as usize);

                    let break_reason = if self.last_pc == registers.pc {
                        info!("Trap detected!  CPU thread paused.");
                        BreakReason::Trap
                    } else if is_stepping {
                        info!("Stepping.  CPU thread paused.");
                        BreakReason::Step
                    } else {
                        info!("Breakpoint hit.  CPU thread paused.");
                        BreakReason::Breakpoint
                    };
                    info!("Breaking @ {:0>4X}", registers.pc);
                    sender.send(DebuggerCommand::Break(break_reason, snapshot)).unwrap();
                }
                thread::park();
            }
        }
        self.last_pc = registers.pc;
    }
}
<commit_msg>Avoid duplicate debug messages<commit_after>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use std::thread;
use std::sync::mpsc::{sync_channel, SyncSender};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use serde_json;
use iron::prelude::*;
use router::Router;
use websocket::{Server as WsServer, Message as WsMessage};

use super::Debugger;
use memory::Memory;
use cpu::registers::Registers;
use self::debugger_command::{DebuggerCommand, BreakReason};
use self::http_handlers::{ToggleBreakpointHandler, ContinueHandler, StepHandler};
use self::breakpoint_map::BreakpointMap;
use self::cpu_snapshot::CpuSnapshot;

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

pub struct HttpDebugger {
    ws_sender: Option<SyncSender<DebuggerCommand>>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    is_stepping: Arc<AtomicBool>,
    prg_offset: u16,
    last_pc: u16,
}

impl HttpDebugger {
    pub fn new(prg_offset: u16) -> Self {
        HttpDebugger {
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            ws_sender: None,
            cpu_thread_handle: thread::current(),
            is_stepping: Arc::new(AtomicBool::new(true)),
            last_pc: 0,
            prg_offset: prg_offset,
        }
    }

    pub fn start(&mut self) -> Result<(), String> {
        if self.ws_sender.is_some() {
            panic!("Start already called.");
        }

        self.start_http_server_thread()?;
        self.start_websocket_thread()?;
        Ok(())
    }

    fn start_websocket_thread(&mut self) -> Result<(), String> {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let (debugger_tx, client_rx) = sync_channel::<DebuggerCommand>(0);
        self.ws_sender = Some(debugger_tx);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).map_err(|e| e.to_string())?;
        info!("Waiting for debugger to attach");
        let connection = ws_server.accept();
        info!("Debugger attached!");
        thread::spawn(move || {
            let request = connection.unwrap().read_request().unwrap();
            request.validate().unwrap();
            let response = request.accept();
            let mut sender = response.send().unwrap();

            while let Ok(debugger_msg) = client_rx.recv() {
                let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                    .unwrap());

                if sender.send_message(&message).is_err() {
                    break;
                }
            }

            info!("Websocket thread is terminating!")
        });

        Ok(())
    }

    fn start_http_server_thread(&self) -> Result<(), String> {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let is_stepping = self.is_stepping.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread.clone(), is_stepping),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints.clone()),
                       "toggle_breakpoint");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });

        Ok(())
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.is_stepping.compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }
}

impl Default for HttpDebugger {
    fn default() -> Self {
        Self::new(0)
    }
}

impl<Mem: Memory> Debugger<Mem> for HttpDebugger {
    fn on_step(&mut self, mem: &Mem, registers: &Registers, cycles: u64) {
        if let Some(ref sender) = self.ws_sender {
            let is_stepping = self.is_stepping.load(Ordering::Relaxed);
            if is_stepping || self.at_breakpoint(registers.pc) || self.last_pc == registers.pc {
                {
                    let snapshot = CpuSnapshot::new(mem.clone(),
                                                    registers.clone(),
                                                    cycles,
                                                    self.prg_offset as usize);

                    let break_reason = if self.last_pc == registers.pc {
                        info!("Trap detected @ {:0>4X}. CPU thread paused.", registers.pc);
                        BreakReason::Trap
                    } else if is_stepping {
                        info!("Stepping @ {:0>4X}.  CPU thread paused.", registers.pc);
                        BreakReason::Step
                    } else {
                        info!("Breakpoint hit @ {:0>4X}.  CPU thread paused.", registers.pc);
                        BreakReason::Breakpoint
                    };
                    sender.send(DebuggerCommand::Break(break_reason, snapshot)).unwrap();
                }
                thread::park();
            }
        }
        self.last_pc = registers.pc;
    }
}
<|endoftext|>


<commit_before>/*!
WARNING: This signature software is a prototype. It has been replaced by the final system
[Ed25519](http://ed25519.cr.yp.to/). It is only kept here for compatibility reasons.
*/
use std::libc::{c_ulonglong, c_int};
use std::vec::{from_elem};
use std::vec::raw::{to_mut_ptr, to_ptr};

#[link(name = "sodium")]
#[link_args = "-lsodium"]
extern {
    fn crypto_sign_edwards25519sha512batch_keypair(pk: *mut u8,
                                                   sk: *mut u8) -> c_int;
    fn crypto_sign_edwards25519sha512batch(sm: *mut u8,
                                           smlen: *mut c_ulonglong,
                                           m: *u8,
                                           mlen: c_ulonglong,
                                           sk: *u8) -> c_int;
    fn crypto_sign_edwards25519sha512batch_open(m: *mut u8,
                                                mlen: *mut c_ulonglong,
                                                sm: *u8,
                                                smlen: c_ulonglong,
                                                pk: *u8) -> c_int;
}

pub static SECRETKEYBYTES: uint = 64;
pub static PUBLICKEYBYTES: uint = 32;
pub static SIGNATUREBYTES: uint = 64;

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey([u8, ..SECRETKEYBYTES]);
impl Drop for SecretKey {
    fn drop(&mut self) {
        for e in self.mut_iter() { *e = 0 }
    }
}
/**
 * `PublicKey` for signatures
 */
pub struct PublicKey([u8, ..PUBLICKEYBYTES]);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
#[fixed_stack_segment]
pub fn gen_keypair() -> (~PublicKey, ~SecretKey) {
    unsafe {
        let mut pk = ~PublicKey([0u8, ..PUBLICKEYBYTES]);
        let mut sk = ~SecretKey([0u8, ..SECRETKEYBYTES]);
        crypto_sign_edwards25519sha512batch_keypair(to_mut_ptr(**pk), to_mut_ptr(**sk));
        (pk, sk)
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
#[fixed_stack_segment]
pub fn sign(m: &[u8], sk: &SecretKey) -> ~[u8] {
    unsafe {
        let mut sm = from_elem(m.len() + SIGNATUREBYTES, 0u8);
        let mut smlen = 0;
        crypto_sign_edwards25519sha512batch(to_mut_ptr(sm),
                                            &mut smlen,
                                            to_ptr(m),
                                            m.len() as c_ulonglong,
                                            to_ptr(**sk));
        sm.truncate(smlen as uint);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
#[fixed_stack_segment]
pub fn verify(sm: &[u8], pk: &PublicKey) -> Option<~[u8]> {
    unsafe {
        let mut m = from_elem(sm.len(), 0u8);
        let mut mlen = 0;
        if crypto_sign_edwards25519sha512batch_open(to_mut_ptr(m),
                                                    &mut mlen,
                                                    to_ptr(sm),
                                                    sm.len() as c_ulonglong,
                                                    to_ptr(**pk)) == 0 {
            m.truncate(mlen as uint);
            Some(m)
        } else {
            None
        }
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for _ in range(0, 256) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(1024);
        let sm = sign(m, sk);
        let m2 = verify(sm, pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for _ in range(0, 32) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(1024);
        let mut sm = sign(m, sk);
        for i in range(0, sm.len()) {
            sm[i] ^= 0x20;
            assert!(None == verify(sm, pk));
            sm[i] ^= 0x20;
        }
    }
}
<commit_msg>lowered the test count for edwards25519sha512batch<commit_after>/*!
WARNING: This signature software is a prototype. It has been replaced by the final system
[Ed25519](http://ed25519.cr.yp.to/). It is only kept here for compatibility reasons.
*/
use std::libc::{c_ulonglong, c_int};
use std::vec::{from_elem};
use std::vec::raw::{to_mut_ptr, to_ptr};

#[link(name = "sodium")]
#[link_args = "-lsodium"]
extern {
    fn crypto_sign_edwards25519sha512batch_keypair(pk: *mut u8,
                                                   sk: *mut u8) -> c_int;
    fn crypto_sign_edwards25519sha512batch(sm: *mut u8,
                                           smlen: *mut c_ulonglong,
                                           m: *u8,
                                           mlen: c_ulonglong,
                                           sk: *u8) -> c_int;
    fn crypto_sign_edwards25519sha512batch_open(m: *mut u8,
                                                mlen: *mut c_ulonglong,
                                                sm: *u8,
                                                smlen: c_ulonglong,
                                                pk: *u8) -> c_int;
}

pub static SECRETKEYBYTES: uint = 64;
pub static PUBLICKEYBYTES: uint = 32;
pub static SIGNATUREBYTES: uint = 64;

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey([u8, ..SECRETKEYBYTES]);
impl Drop for SecretKey {
    fn drop(&mut self) {
        for e in self.mut_iter() { *e = 0 }
    }
}
/**
 * `PublicKey` for signatures
 */
pub struct PublicKey([u8, ..PUBLICKEYBYTES]);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
#[fixed_stack_segment]
pub fn gen_keypair() -> (~PublicKey, ~SecretKey) {
    unsafe {
        let mut pk = ~PublicKey([0u8, ..PUBLICKEYBYTES]);
        let mut sk = ~SecretKey([0u8, ..SECRETKEYBYTES]);
        crypto_sign_edwards25519sha512batch_keypair(to_mut_ptr(**pk), to_mut_ptr(**sk));
        (pk, sk)
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
#[fixed_stack_segment]
pub fn sign(m: &[u8], sk: &SecretKey) -> ~[u8] {
    unsafe {
        let mut sm = from_elem(m.len() + SIGNATUREBYTES, 0u8);
        let mut smlen = 0;
        crypto_sign_edwards25519sha512batch(to_mut_ptr(sm),
                                            &mut smlen,
                                            to_ptr(m),
                                            m.len() as c_ulonglong,
                                            to_ptr(**sk));
        sm.truncate(smlen as uint);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
#[fixed_stack_segment]
pub fn verify(sm: &[u8], pk: &PublicKey) -> Option<~[u8]> {
    unsafe {
        let mut m = from_elem(sm.len(), 0u8);
        let mut mlen = 0;
        if crypto_sign_edwards25519sha512batch_open(to_mut_ptr(m),
                                                    &mut mlen,
                                                    to_ptr(sm),
                                                    sm.len() as c_ulonglong,
                                                    to_ptr(**pk)) == 0 {
            m.truncate(mlen as uint);
            Some(m)
        } else {
            None
        }
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for _ in range(0, 32) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(1024);
        let sm = sign(m, sk);
        let m2 = verify(sm, pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for _ in range(0, 32) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(1024);
        let mut sm = sign(m, sk);
        for i in range(0, sm.len()) {
            sm[i] ^= 0x20;
            assert!(None == verify(sm, pk));
            sm[i] ^= 0x20;
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use progress::frontier::MutableAntichain;
use progress::Timestamp;
use progress::count_map::CountMap;
use dataflow::operators::Capability;

/// Tracks requests for notification and delivers available notifications.
///
/// Notificator is meant to manage the delivery of requested notifications in the presence of
/// inputs that may have outstanding messages to deliver. The notificator tracks the frontiers,
/// as presented from the outside, for each input. Requested notifications can be served only
/// once there are no frontier elements less-or-equal to them, and there are no other pending
/// notification requests less than them. Each with be less-or-equal to itself, so we want to
/// dodge that corner case.
pub struct Notificator<T: Timestamp> {
    pending: Vec<Capability<T>>,
    frontier: Vec<MutableAntichain<T>>,
    available: VecDeque<(Capability<T>, i64)>,
}

impl<T: Timestamp> Notificator<T> {
    pub fn new() -> Notificator<T> {
        Notificator {
            pending: Vec::new(),
            frontier: Vec::new(),
            available: VecDeque::new(),
        }
    }

    /// Updates the `Notificator`'s frontiers from a `CountMap` per input.
    pub fn update_frontier_from_cm(&mut self, count_map: &mut [CountMap<T>]) {
        while self.frontier.len() < count_map.len() {
            self.frontier.push(MutableAntichain::new());
        }

        for (index, counts) in count_map.iter_mut().enumerate() {
            while let Some((time, delta)) = counts.pop() {
                self.frontier[index].update(&time, delta);
            }
        }
    }

    /// Reveals the elements in the frontier of the indicated input.
    pub fn frontier(&self, input: usize) -> &[T] {
        self.frontier[input].elements()
    }

    /// Requests a notification at the time associated with capability `cap`. Takes ownership of
    /// the capability.
    ///
    /// In order to request a notification at future timestamp, obtain a capability for the new
    /// timestamp first, as show in the example.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Unary};
    /// use timely::dataflow::channels::pact::Pipeline;
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .unary_notify(Pipeline, "example", Vec::new(), |input, output, notificator| {
    ///                while let Some((cap, data)) = input.next() {
    ///                    output.session(&cap).give_content(data);
    ///                    let mut time = cap.time();
    ///                    time.inner += 1;
    ///                    notificator.notify_at(cap.delayed(&time));
    ///                }
    ///                while let Some((cap, count)) = notificator.next() {
    ///                    println!("done with time: {:?}", cap.time());
    ///                }
    ///            });
    /// });
    /// ```
    #[inline]
    pub fn notify_at(&mut self, cap: Capability<T>) {
        self.pending.push(cap);
    }

    /// Repeatedly calls `logic` till exhaustion of the available notifications.
    ///
    /// `logic` receives a capability for `t`, the timestamp being notified and a `count`
    /// representing how many capabilities were requested for that specific timestamp.
    #[inline]
    pub fn for_each<F: FnMut(Capability<T>, i64)>(&mut self, mut logic: F) {
        while let Some((cap, count)) = self.next() {
            ::logging::log(&::logging::GUARDED_PROGRESS, true);
            logic(cap, count);
            ::logging::log(&::logging::GUARDED_PROGRESS, false);
        }
    }

    #[inline]
    fn scan_for_available_notifications(&mut self) {
        let mut last = 0;
        while let Some(position) = (&self.pending[last..]).iter().position(|cap| {
            let time = cap.time();
            !self.frontier.iter().any(|x| x.le(&time))
        }) {
            let newly_available = self.pending.swap_remove(position + last);
            let push_new = {
                let already_available = self.available.iter_mut().find(|&&mut (ref cap, _)| {
                    cap.time() == newly_available.time()
                });
                match already_available {
                    Some(&mut (_, ref mut count)) => {
                        *count += 1;
                        false
                    },
                    None => true,
                }
            };
            if push_new {
                self.available.push_back((newly_available, 1));
            }
            last = position;
        }
    }
}

impl<T: Timestamp> Iterator for Notificator<T> {
    type Item = (Capability<T>, i64);

    /// Retrieve the next available notification.
    ///
    /// Returns `None` if no notification is available. Returns `Some(cap, count)` otherwise:
    /// `cap` is a a capability for `t`, the timestamp being notified and, `count` represents
    /// how many capabilities were requested for that specific timestamp.
    fn next(&mut self) -> Option<(Capability<T>, i64)> {
        if self.available.len() == 0 {
            self.scan_for_available_notifications();
        }

        self.available.pop_front()
    }
}

<commit_msg>notificator now delivers notifications in some topological order<commit_after>use progress::frontier::MutableAntichain;
use progress::Timestamp;
use progress::count_map::CountMap;
use dataflow::operators::Capability;

/// Tracks requests for notification and delivers available notifications.
///
/// Notificator is meant to manage the delivery of requested notifications in the presence of
/// inputs that may have outstanding messages to deliver. The notificator tracks the frontiers,
/// as presented from the outside, for each input. Requested notifications can be served only
/// once there are no frontier elements less-or-equal to them, and there are no other pending
/// notification requests less than them. Each with be less-or-equal to itself, so we want to
/// dodge that corner case.
pub struct Notificator<T: Timestamp> {
    pending: Vec<(Capability<T>, u64)>,
    frontier: Vec<MutableAntichain<T>>,
    available: Vec<(Capability<T>, u64)>,
    candidates: Vec<(Capability<T>, u64)>,
}

impl<T: Timestamp> Notificator<T> {
    pub fn new() -> Notificator<T> {
        Notificator {
            pending: Vec::new(),
            frontier: Vec::new(),
            available: Vec::new(),
            candidates: Vec::new(),
        }
    }

    /// Updates the `Notificator`'s frontiers from a `CountMap` per input.
    pub fn update_frontier_from_cm(&mut self, count_map: &mut [CountMap<T>]) {
        while self.frontier.len() < count_map.len() {
            self.frontier.push(MutableAntichain::new());
        }

        for (index, counts) in count_map.iter_mut().enumerate() {
            while let Some((time, delta)) = counts.pop() {
                self.frontier[index].update(&time, delta);
            }
        }
    }

    /// Reveals the elements in the frontier of the indicated input.
    pub fn frontier(&self, input: usize) -> &[T] {
        self.frontier[input].elements()
    }

    /// Requests a notification at the time associated with capability `cap`. Takes ownership of
    /// the capability.
    ///
    /// In order to request a notification at future timestamp, obtain a capability for the new
    /// timestamp first, as show in the example.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Unary};
    /// use timely::dataflow::channels::pact::Pipeline;
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .unary_notify(Pipeline, "example", Vec::new(), |input, output, notificator| {
    ///                while let Some((cap, data)) = input.next() {
    ///                    output.session(&cap).give_content(data);
    ///                    let mut time = cap.time();
    ///                    time.inner += 1;
    ///                    notificator.notify_at(cap.delayed(&time));
    ///                }
    ///                while let Some((cap, count)) = notificator.next() {
    ///                    println!("done with time: {:?}", cap.time());
    ///                }
    ///            });
    /// });
    /// ```
    #[inline]
    pub fn notify_at(&mut self, cap: Capability<T>) {
        let push = if let Some(&mut (_, ref mut count)) =
            self.pending.iter_mut().find(|&&mut (ref c, _)| c.time().eq(&cap.time())) {
                *count += 1;
                None
            } else {
                Some((cap, 1))
            };
        if let Some(p) = push {
            self.pending.push(p);
        }
    }

    /// Repeatedly calls `logic` till exhaustion of the available notifications.
    ///
    /// `logic` receives a capability for `t`, the timestamp being notified and a `count`
    /// representing how many capabilities were requested for that specific timestamp.
    #[inline]
    pub fn for_each<F: FnMut(Capability<T>, u64)>(&mut self, mut logic: F) {
        while let Some((cap, count)) = self.next() {
            ::logging::log(&::logging::GUARDED_PROGRESS, true);
            logic(cap, count);
            ::logging::log(&::logging::GUARDED_PROGRESS, false);
        }
    }
}

impl<T: Timestamp> Iterator for Notificator<T> {
    type Item = (Capability<T>, u64);

    /// Retrieve the next available notification.
    ///
    /// Returns `None` if no notification is available. Returns `Some(cap, count)` otherwise:
    /// `cap` is a a capability for `t`, the timestamp being notified and, `count` represents
    /// how many notifications (out of those requested) are being delivered for that specific
    /// timestamp.
    fn next(&mut self) -> Option<(Capability<T>, u64)> {
        if self.available.len() == 0 {
            let mut available = &mut self.available; // available is empty
            let mut pending = &mut self.pending;
            let mut candidates = &mut self.candidates;
            assert!(candidates.len() == 0);
            let frontier = &self.frontier;

            pending.drain_into_if(&mut candidates, |&(ref cap, _)| {
                !frontier.iter().any(|x| x.le(&cap.time()))
            });

            while let Some((cap, count)) = candidates.pop() {
                let mut cap_in_minimal_antichain = available.len() == 0;
                available.drain_into_if(&mut pending, |&(ref avail_cap, _)| {
                    let cap_lt_available = cap.time().lt(&avail_cap.time());
                    cap_in_minimal_antichain |= cap_lt_available ||
                        cap.time().partial_cmp(&avail_cap.time()).is_none();
                    cap_lt_available
                });
                if cap_in_minimal_antichain {
                    available.push((cap, count));
                } else {
                    pending.push((cap, count));
                }
            }
        }

        self.available.pop()
    }
}

trait DrainIntoIf<T> {
    /// Invokes "P" on each element of "source" (exactly once) and moves the matching values to
    /// "target". Ordering is not preserved.
    fn drain_into_if<P>(&mut self, target: &mut Vec<T>, p: P) -> () where P: FnMut(&T) -> bool;
}

impl<T> DrainIntoIf<T> for Vec<T> {
    fn drain_into_if<P>(&mut self, target: &mut Vec<T>, mut p: P) -> () where P: FnMut(&T) -> bool {
        let mut i = 0;
        while i < self.len() {
            let matches = {
                let v = &mut **self;
                p(&v[i])
            };
            if matches {
                target.push(self.swap_remove(i));
            } else {
                i += 1;
            }
        }
    }
}

#[test]
fn drain_into_if_behaves_correctly() {
    let mut v = vec![3, 10, 4, 5, 13, 7, 2, 1];
    let mut v1 = Vec::new();
    v.drain_into_if(&mut v1, |x| x >= &5);
    v.sort();
    v1.sort();
    assert!(v == vec![1, 2, 3, 4]);
    assert!(v1 == vec![5, 7, 10, 13]);
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::{cmp, panic};
use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use devicemapper::{Bytes, IEC, Sectors};

use super::logger::init_logger;
use super::util::clean_up;

use super::super::device::wipe_sectors;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device for the given path.
    /// Wipe initial MiB to clear metadata.
    pub fn new(path: &Path) -> RealTestDev {
        wipe_sectors(path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev { path: PathBuf::from(path) }
    }

    /// Get the device node of the device.
    fn as_path(&self) -> &Path {
        &self.path
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(&self.path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

pub enum DeviceLimits {
    Exactly(usize),
    AtLeast(usize),
    #[allow(dead_code)]
    Range(usize, usize), // inclusive
}

/// Get a list of counts of devices to use for tests.
/// None of the counts can be greater than avail.
fn get_device_counts(limits: DeviceLimits, avail: usize) -> Vec<usize> {
    // Convert enum to [lower, Option<upper>) values
    let (lower, maybe_upper) = match limits {
        DeviceLimits::Exactly(num) => (num, Some(num + 1)),
        DeviceLimits::AtLeast(num) => (num, None),
        DeviceLimits::Range(lower, upper) => {
            assert!(lower < upper);
            (lower, Some(upper + 1))
        }
    };

    let mut counts = vec![];

    // Check these values against available blockdevs
    if lower > avail {
        return counts;
    }

    counts.push(lower);

    if lower != avail {
        match maybe_upper {
            None => counts.push(avail),
            Some(upper) => {
                if lower + 1 < upper {
                    counts.push(cmp::min(upper - 1, avail))
                }
            }
        }
    }

    counts
}

/// Run test on real devices, using given constraints. Constraints may result
/// in multiple invocations of the test, with differing numbers of block
/// devices.
pub fn test_with_spec<F>(limits: DeviceLimits, test: F) -> ()
    where F: Fn(&[&Path]) -> () + panic::RefUnwindSafe
{
    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths: Vec<_> = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap()
        .iter()
        .map(|x| Path::new(x.as_str().unwrap()))
        .collect();

    let counts = get_device_counts(limits, devpaths.len());

    assert!(!counts.is_empty());

    init_logger();

    let runs = counts
        .iter()
        .map(|num| devpaths.iter().take(*num).collect::<Vec<_>>());

    for run_paths in runs {
        let devices: Vec<_> = run_paths.iter().map(|x| RealTestDev::new(x)).collect();

        clean_up().unwrap();

        let result =
            panic::catch_unwind(|| test(&devices.iter().map(|x| x.as_path()).collect::<Vec<_>>()));
        let tear_down = clean_up();

        result.unwrap();
        tear_down.unwrap();
    }
}
<commit_msg>Remove obsoleted allow(dead-code)<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::{cmp, panic};
use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use devicemapper::{Bytes, IEC, Sectors};

use super::logger::init_logger;
use super::util::clean_up;

use super::super::device::wipe_sectors;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device for the given path.
    /// Wipe initial MiB to clear metadata.
    pub fn new(path: &Path) -> RealTestDev {
        wipe_sectors(path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev { path: PathBuf::from(path) }
    }

    /// Get the device node of the device.
    fn as_path(&self) -> &Path {
        &self.path
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(&self.path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

pub enum DeviceLimits {
    Exactly(usize),
    AtLeast(usize),
    Range(usize, usize), // inclusive
}

/// Get a list of counts of devices to use for tests.
/// None of the counts can be greater than avail.
fn get_device_counts(limits: DeviceLimits, avail: usize) -> Vec<usize> {
    // Convert enum to [lower, Option<upper>) values
    let (lower, maybe_upper) = match limits {
        DeviceLimits::Exactly(num) => (num, Some(num + 1)),
        DeviceLimits::AtLeast(num) => (num, None),
        DeviceLimits::Range(lower, upper) => {
            assert!(lower < upper);
            (lower, Some(upper + 1))
        }
    };

    let mut counts = vec![];

    // Check these values against available blockdevs
    if lower > avail {
        return counts;
    }

    counts.push(lower);

    if lower != avail {
        match maybe_upper {
            None => counts.push(avail),
            Some(upper) => {
                if lower + 1 < upper {
                    counts.push(cmp::min(upper - 1, avail))
                }
            }
        }
    }

    counts
}

/// Run test on real devices, using given constraints. Constraints may result
/// in multiple invocations of the test, with differing numbers of block
/// devices.
pub fn test_with_spec<F>(limits: DeviceLimits, test: F) -> ()
    where F: Fn(&[&Path]) -> () + panic::RefUnwindSafe
{
    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths: Vec<_> = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap()
        .iter()
        .map(|x| Path::new(x.as_str().unwrap()))
        .collect();

    let counts = get_device_counts(limits, devpaths.len());

    assert!(!counts.is_empty());

    init_logger();

    let runs = counts
        .iter()
        .map(|num| devpaths.iter().take(*num).collect::<Vec<_>>());

    for run_paths in runs {
        let devices: Vec<_> = run_paths.iter().map(|x| RealTestDev::new(x)).collect();

        clean_up().unwrap();

        let result =
            panic::catch_unwind(|| test(&devices.iter().map(|x| x.as_path()).collect::<Vec<_>>()));
        let tear_down = clean_up();

        result.unwrap();
        tear_down.unwrap();
    }
}
<|endoftext|>


<commit_before>
<commit_msg>rustup integration #122 tests<commit_after>use super::*;

#[test]
fn is_crate_installed_true() {
    let output = is_crate_installed("cargo", "--version");
    assert!(output);
}

#[test]
fn is_crate_installed_false() {
    let output = is_crate_installed("cargo_bad", "--version");
    assert!(!output);
}

#[test]
fn invoke_rustup_install_none() {
    let info = InstallCrateInfo {
        crate_name: "bad_crate_name".to_string(),
        binary: "test".to_string(),
        test_arg: "--help".to_string(),
        rustup_component_name: None,
    };

    let output = invoke_rustup_install(&info);
    assert!(!output);
}

#[test]
fn invoke_rustup_install_fail() {
    let info = InstallCrateInfo {
        crate_name: "bad_crate_name".to_string(),
        binary: "test".to_string(),
        test_arg: "--help".to_string(),
        rustup_component_name: Some("unknown_rustup_component_test".to_string()),
    };

    let output = invoke_rustup_install(&info);
    assert!(!output);
}

#[test]
fn invoke_cargo_install_test() {
    let info = InstallCrateInfo {
        crate_name: "bad_crate_name".to_string(),
        binary: "cargo_bad".to_string(),
        test_arg: "--help".to_string(),
        rustup_component_name: Some("unknown_rustup_component_test".to_string()),
    };

    invoke_cargo_install(&info, &None, false);
}

#[test]
fn install_crate_test() {
    let info = InstallCrateInfo {
        crate_name: "bad_crate_name".to_string(),
        binary: "cargo_bad".to_string(),
        test_arg: "--help".to_string(),
        rustup_component_name: Some("unknown_rustup_component_test".to_string()),
    };

    install_crate(&info, &None, false);
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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 rustc::ty::TypeFoldable;
use rustc::ty::subst::{Kind, Substs};
use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, Lookup};
use rustc::mir::transform::{MirPass, MirSource};
use rustc::infer::{self, InferCtxt};
use syntax_pos::DUMMY_SP;
use std::collections::HashMap;

#[allow(dead_code)]
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    lookup_map: HashMap<RegionVid, Lookup>,
    infcx: InferCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
    pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
        NLLVisitor {
            infcx,
            lookup_map: HashMap::new(),
        }
    }

    pub fn into_results(self) -> HashMap<RegionVid, Lookup> {
        self.lookup_map
    }

    fn renumber_regions<T>(&self, value: &T) -> T where T: TypeFoldable<'tcx> {
        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
            self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP))
        })
    }

    fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
        if let RegionKind::ReVar(rid) = *region {
            self.lookup_map.entry(rid).or_insert(lookup);
        }
    }

    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
        for region in ty.regions() {
            self.store_region(region, lookup);
        }
    }

    fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
        if let Some(ty) = kind.as_type() {
            self.store_ty_regions(&ty, lookup);
        } else if let Some(region) = kind.as_region() {
            self.store_region(region, lookup);
        }
    }
}

impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
        let old_ty = *ty;
        *ty = self.renumber_regions(&old_ty);
        self.store_ty_regions(ty, lookup);
    }

    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
        *substs = self.renumber_regions(&{*substs});
        let lookup = Lookup::Loc(location);
        for kind in *substs {
            self.store_kind_regions(kind, lookup);
        }
    }

    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
        match *rvalue {
            Rvalue::Ref(ref mut r, _, _) => {
                let old_r = *r;
                *r = self.renumber_regions(&old_r);
                let lookup = Lookup::Loc(location);
                self.store_region(r, lookup);
            }
            Rvalue::Use(..) |
            Rvalue::Repeat(..) |
            Rvalue::Len(..) |
            Rvalue::Cast(..) |
            Rvalue::BinaryOp(..) |
            Rvalue::CheckedBinaryOp(..) |
            Rvalue::UnaryOp(..) |
            Rvalue::Discriminant(..) |
            Rvalue::NullaryOp(..) |
            Rvalue::Aggregate(..) => {
                // These variants don't contain regions.
            }
        }
        self.super_rvalue(rvalue, location);
    }

    fn visit_closure_substs(&mut self,
                            substs: &mut ClosureSubsts<'tcx>,
                            location: Location) {
        *substs = self.renumber_regions(substs);
        let lookup = Lookup::Loc(location);
        for kind in substs.substs {
            self.store_kind_regions(kind, lookup);
        }
    }

    fn visit_statement(&mut self,
                       block: BasicBlock,
                       statement: &mut Statement<'tcx>,
                       location: Location) {
        if let StatementKind::EndRegion(_) = statement.kind {
            statement.kind = StatementKind::Nop;
        }
        self.super_statement(block, statement, location);
    }
}

// MIR Pass for non-lexical lifetimes
pub struct NLL;

impl MirPass for NLL {
    fn run_pass<'a, 'tcx>(&self,
                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          _: MirSource,
                          mir: &mut Mir<'tcx>) {
        if !tcx.sess.opts.debugging_opts.nll {
            return;
        }

        tcx.infer_ctxt().enter(|infcx| {
            // Clone mir so we can mutate it without disturbing the rest of the compiler
            let mut renumbered_mir = mir.clone();
            let mut visitor = NLLVisitor::new(infcx);
            visitor.visit_mir(&mut renumbered_mir);
            let _results = visitor.into_results();
        })
    }
}<commit_msg>Store a new Region value every time we create a new region variable<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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 rustc::ty::TypeFoldable;
use rustc::ty::subst::{Kind, Substs};
use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, Lookup};
use rustc::mir::transform::{MirPass, MirSource};
use rustc::infer::{self, InferCtxt};
use rustc::util::nodemap::FxHashSet;
use syntax_pos::DUMMY_SP;
use std::collections::HashMap;

#[allow(dead_code)]
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    lookup_map: HashMap<RegionVid, Lookup>,
    regions: Vec<Region>,
    infcx: InferCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
    pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
        NLLVisitor {
            infcx,
            lookup_map: HashMap::new(),
            regions: vec![],
        }
    }

    pub fn into_results(self) -> HashMap<RegionVid, Lookup> {
        self.lookup_map
    }

    fn renumber_regions<T>(&mut self, value: &T) -> T where T: TypeFoldable<'tcx> {
        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
            self.regions.push(Region::default());
            self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP))
        })
    }

    fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
        if let RegionKind::ReVar(rid) = *region {
            self.lookup_map.entry(rid).or_insert(lookup);
        }
    }

    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
        for region in ty.regions() {
            self.store_region(region, lookup);
        }
    }

    fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
        if let Some(ty) = kind.as_type() {
            self.store_ty_regions(&ty, lookup);
        } else if let Some(region) = kind.as_region() {
            self.store_region(region, lookup);
        }
    }
}

impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
        let old_ty = *ty;
        *ty = self.renumber_regions(&old_ty);
        self.store_ty_regions(ty, lookup);
    }

    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
        *substs = self.renumber_regions(&{*substs});
        let lookup = Lookup::Loc(location);
        for kind in *substs {
            self.store_kind_regions(kind, lookup);
        }
    }

    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
        match *rvalue {
            Rvalue::Ref(ref mut r, _, _) => {
                let old_r = *r;
                *r = self.renumber_regions(&old_r);
                let lookup = Lookup::Loc(location);
                self.store_region(r, lookup);
            }
            Rvalue::Use(..) |
            Rvalue::Repeat(..) |
            Rvalue::Len(..) |
            Rvalue::Cast(..) |
            Rvalue::BinaryOp(..) |
            Rvalue::CheckedBinaryOp(..) |
            Rvalue::UnaryOp(..) |
            Rvalue::Discriminant(..) |
            Rvalue::NullaryOp(..) |
            Rvalue::Aggregate(..) => {
                // These variants don't contain regions.
            }
        }
        self.super_rvalue(rvalue, location);
    }

    fn visit_closure_substs(&mut self,
                            substs: &mut ClosureSubsts<'tcx>,
                            location: Location) {
        *substs = self.renumber_regions(substs);
        let lookup = Lookup::Loc(location);
        for kind in substs.substs {
            self.store_kind_regions(kind, lookup);
        }
    }

    fn visit_statement(&mut self,
                       block: BasicBlock,
                       statement: &mut Statement<'tcx>,
                       location: Location) {
        if let StatementKind::EndRegion(_) = statement.kind {
            statement.kind = StatementKind::Nop;
        }
        self.super_statement(block, statement, location);
    }
}

// MIR Pass for non-lexical lifetimes
pub struct NLL;

impl MirPass for NLL {
    fn run_pass<'a, 'tcx>(&self,
                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          _: MirSource,
                          mir: &mut Mir<'tcx>) {
        if !tcx.sess.opts.debugging_opts.nll {
            return;
        }

        tcx.infer_ctxt().enter(|infcx| {
            // Clone mir so we can mutate it without disturbing the rest of the compiler
            let mut renumbered_mir = mir.clone();
            let mut visitor = NLLVisitor::new(infcx);
            visitor.visit_mir(&mut renumbered_mir);
            let _results = visitor.into_results();
        })
    }
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
struct Region {
    points: FxHashSet<Location>,
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate asn1_cereal;

use std::io;

use asn1_cereal::serial::{Asn1Serialize, Asn1Deserialize};
use asn1_cereal::enc::{DER, BER};
use asn1_cereal::tag::Class;

fn main() {
  let mut buffer: Vec<u8> = Vec::new();
  // let mut buffer = io::BufWriter::new(io::stdout());
  let seq = IntSequence { a: 3, b: 4, c: SomeString("Hello".into()) };
  {
    let mut writer = io::BufWriter::new(&mut buffer);
    seq.serialize_enc(DER, &mut writer).unwrap();
  };
  println!("{:?}", buffer);
  {
    let mut reader = buffer.iter().map(|x| Ok(*x) as Result<u8, std::io::Error>);
    let seq = IntSequence::deserialize_enc(DER, &mut reader).unwrap();
    println!("{:?}", seq);
  }
}

#[derive(Debug)]
struct SomeString(String);

asn1_info!(
  SomeString,
  Class::Private,
  1,
  true,
  "SOMESTRING"
);

asn1_newtype!(SomeString);

#[derive(Debug)]
struct IntSequence {
  a: u64,
  b: u64,
  c: SomeString,
}

asn1_sequence!(
  IntSequence,
  "INTSEQ",
  a,
  b,
  c
);
<commit_msg>Add a --dump option to simple.rs<commit_after>#[macro_use]
extern crate asn1_cereal;
extern crate argparse;

use std::io;

use asn1_cereal::serial::{Asn1Serialize, Asn1Deserialize};
use asn1_cereal::enc::{DER, BER, BERAlt};
use asn1_cereal::tag::Class;
use argparse::{ArgumentParser, StoreTrue};

fn main() {
  let opts = parse_args();

  let mut buffer: Vec<u8> = Vec::new();
  let mut output = io::BufWriter::new(io::stdout());

  let seq = IntSequence { a: 3, b: 4, c: SomeString("Hello".into()) };

  if opts.dump {
    let mut writer = io::BufWriter::new(&mut output);
    seq.serialize_enc(BERAlt, &mut writer).unwrap();
    return;
  }
  {
    let mut writer = io::BufWriter::new(&mut buffer);
    seq.serialize_enc(BERAlt, &mut writer).unwrap();
  }
  println!("{:?}", buffer);
  {
    let mut reader = buffer.iter().map(|x| Ok(*x) as Result<u8, std::io::Error>);
    let seq = IntSequence::deserialize_enc(DER, &mut reader).unwrap();
    println!("{:?}", seq);
  }
}

#[derive(Debug)]
struct SomeString(String);

asn1_info!(
  SomeString,
  Class::Private,
  1,
  true,
  "SOMESTRING"
);

asn1_newtype!(SomeString);

#[derive(Debug)]
struct IntSequence {
  a: u64,
  b: u64,
  c: SomeString,
}

asn1_sequence!(
  IntSequence,
  "INTSEQ",
  a,
  b,
  c
);

struct ProgOpts {
  dump: bool,
}

fn parse_args() -> ProgOpts {
  let mut opts = ProgOpts {
    dump: false,
  };
  {
    let mut ap = ArgumentParser::new();
    ap.refer(&mut opts.dump)
      .add_option(&["-d", "--dump"], StoreTrue, "Dump asn.1 packet");
    ap.parse_args_or_exit();
  }
  opts
}
<|endoftext|>