<commit_before>use cairo::{self, MatrixTrait};
use cairo_sys;
use glib::translate::*;
use std::cell::Cell;

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
use handle::RsvgHandle;
use length::{Length, LengthDir};
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{parse, parse_and_validate, Parse};
use property_bag::PropertyBag;
use state::Opacity;

coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);

// remove this once cairo-rs has this mask_surface()
fn cairo_mask_surface(cr: &cairo::Context, surface: &cairo::Surface, x: f64, y: f64) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        cairo_sys::cairo_mask_surface(raw_cr, surface.to_raw_none(), x, y);
    }
}

pub struct NodeMask {
    x: Cell<Length>,
    y: Cell<Length>,
    width: Cell<Length>,
    height: Cell<Length>,

    units: Cell<MaskUnits>,
    content_units: Cell<MaskContentUnits>,
}

impl NodeMask {
    pub fn new() -> NodeMask {
        NodeMask {
            x: Cell::new(NodeMask::get_default_pos(LengthDir::Horizontal)),
            y: Cell::new(NodeMask::get_default_pos(LengthDir::Vertical)),

            width: Cell::new(NodeMask::get_default_size(LengthDir::Horizontal)),
            height: Cell::new(NodeMask::get_default_size(LengthDir::Vertical)),

            units: Cell::new(MaskUnits::default()),
            content_units: Cell::new(MaskContentUnits::default()),
        }
    }

    fn get_default_pos(dir: LengthDir) -> Length {
        Length::parse_str("-10%", dir).unwrap()
    }

    fn get_default_size(dir: LengthDir) -> Length {
        Length::parse_str("120%", dir).unwrap()
    }

    pub fn generate_cairo_mask(
        &self,
        node: &RsvgNode,
        affine_before_mask: &cairo::Matrix,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<(), RenderingError> {
        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();

        let width = draw_ctx.get_width() as i32;
        let height = draw_ctx.get_height() as i32;

        let mut surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;

        let mask_units = CoordUnits::from(self.units.get());
        let content_units = CoordUnits::from(self.content_units.get());

        if mask_units == CoordUnits::ObjectBoundingBox {
            draw_ctx.push_view_box(1.0, 1.0);
        }

        let x = self.x.get().normalize(&values, draw_ctx);
        let y = self.y.get().normalize(&values, draw_ctx);
        let w = self.width.get().normalize(&values, draw_ctx);
        let h = self.height.get().normalize(&values, draw_ctx);

        if mask_units == CoordUnits::ObjectBoundingBox {
            draw_ctx.pop_view_box();
        }

        // Use a scope because mask_cr needs to release the
        // reference to the surface before we access the pixels
        {
            let bbox_rect = {
                if let Some(ref rect) = draw_ctx.get_bbox().rect {
                    *rect
                } else {
                    // The node being masked is empty / doesn't have a
                    // bounding box, so there's nothing to mask!
                    return Ok(());
                }
            };

            let save_cr = draw_ctx.get_cairo_context();

            let mask_cr = cairo::Context::new(&surface);
            mask_cr.set_matrix(*affine_before_mask);
            mask_cr.transform(node.get_transform());

            draw_ctx.set_cairo_context(&mask_cr);

            if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.clip(
                    x * bbox_rect.width + bbox_rect.x,
                    y * bbox_rect.height + bbox_rect.y,
                    w * bbox_rect.width,
                    h * bbox_rect.height,
                );
            } else {
                draw_ctx.clip(x, y, w, h);
            }

            if content_units == CoordUnits::ObjectBoundingBox {
                let bbtransform = cairo::Matrix::new(
                    bbox_rect.width,
                    0.0,
                    0.0,
                    bbox_rect.height,
                    bbox_rect.x,
                    bbox_rect.y,
                );

                mask_cr.transform(bbtransform);

                draw_ctx.push_view_box(1.0, 1.0);
            }

            let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
                node.draw_children(&cascaded, dc, false)
            });

            if content_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.pop_view_box();
            }

            draw_ctx.set_cairo_context(&save_cr);

            res
        }?;

        {
            let rowstride = surface.get_stride() as usize;
            let mut pixels = surface.get_data().unwrap();
            let opacity = {
                let Opacity(o) = values.opacity;
                u8::from(o)
            };

            for row in pixels.chunks_mut(rowstride) {
                for p in row[..4 * width as usize].chunks_mut(4) {
                    //  Assuming, the pixel is linear RGB (not sRGB)
                    //  y = luminance
                    //  Y = 0.2126 R + 0.7152 G + 0.0722 B
                    //  1.0 opacity = 255
                    //
                    //  When Y = 1.0, pixel for mask should be 0xFFFFFFFF
                    //    (you get 1.0 luminance from 255 from R, G and B)
                    //
                    // r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45  ~= 14042
                    // g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69  ~= 47240
                    // b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 =  4768.88  ~= 4769
                    //
                    // This allows for the following expected behaviour:
                    //    (we only care about the most sig byte)
                    // if pixel = 0x00FFFFFF, pixel' = 0xFF......
                    // if pixel = 0x00020202, pixel' = 0x02......
                    // if pixel = 0x00000000, pixel' = 0x00......
                    //
                    // NOTE: the following assumes little-endian
                    let (r, g, b, o) = (p[2] as u32, p[1] as u32, p[0] as u32, opacity as u32);
                    p[3] = (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8;
                }
            }
        }

        let cr = draw_ctx.get_cairo_context();

        cr.identity_matrix();

        let (xofs, yofs) = draw_ctx.get_offset();
        cairo_mask_surface(&cr, &surface, xofs, yofs);

        Ok(())
    }
}

impl NodeTrait for NodeMask {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(parse("x", value, LengthDir::Horizontal)?),
                Attribute::Y => self.y.set(parse("y", value, LengthDir::Vertical)?),
                Attribute::Width => self.width.set(parse_and_validate(
                    "width",
                    value,
                    LengthDir::Horizontal,
                    Length::check_nonnegative,
                )?),
                Attribute::Height => self.height.set(parse_and_validate(
                    "height",
                    value,
                    LengthDir::Vertical,
                    Length::check_nonnegative,
                )?),

                Attribute::MaskUnits => self.units.set(parse("maskUnits", value, ())?),

                Attribute::MaskContentUnits => {
                    self.content_units
                        .set(parse("maskContentUnits", value, ())?)
                }

                _ => (),
            }
        }

        Ok(())
    }
}
<commit_msg>compute_luminance_to_alpha(): Take ownership of the surface; return it again<commit_after>use cairo::{self, MatrixTrait};
use cairo_sys;
use glib::translate::*;
use std::cell::Cell;

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
use handle::RsvgHandle;
use length::{Length, LengthDir};
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{parse, parse_and_validate, Parse};
use property_bag::PropertyBag;
use state::Opacity;

coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);

// remove this once cairo-rs has this mask_surface()
fn cairo_mask_surface(cr: &cairo::Context, surface: &cairo::Surface, x: f64, y: f64) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        cairo_sys::cairo_mask_surface(raw_cr, surface.to_raw_none(), x, y);
    }
}

pub struct NodeMask {
    x: Cell<Length>,
    y: Cell<Length>,
    width: Cell<Length>,
    height: Cell<Length>,

    units: Cell<MaskUnits>,
    content_units: Cell<MaskContentUnits>,
}

impl NodeMask {
    pub fn new() -> NodeMask {
        NodeMask {
            x: Cell::new(NodeMask::get_default_pos(LengthDir::Horizontal)),
            y: Cell::new(NodeMask::get_default_pos(LengthDir::Vertical)),

            width: Cell::new(NodeMask::get_default_size(LengthDir::Horizontal)),
            height: Cell::new(NodeMask::get_default_size(LengthDir::Vertical)),

            units: Cell::new(MaskUnits::default()),
            content_units: Cell::new(MaskContentUnits::default()),
        }
    }

    fn get_default_pos(dir: LengthDir) -> Length {
        Length::parse_str("-10%", dir).unwrap()
    }

    fn get_default_size(dir: LengthDir) -> Length {
        Length::parse_str("120%", dir).unwrap()
    }

    pub fn generate_cairo_mask(
        &self,
        node: &RsvgNode,
        affine_before_mask: &cairo::Matrix,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<(), RenderingError> {
        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();

        let width = draw_ctx.get_width() as i32;
        let height = draw_ctx.get_height() as i32;

        let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;

        let mask_units = CoordUnits::from(self.units.get());
        let content_units = CoordUnits::from(self.content_units.get());

        if mask_units == CoordUnits::ObjectBoundingBox {
            draw_ctx.push_view_box(1.0, 1.0);
        }

        let x = self.x.get().normalize(&values, draw_ctx);
        let y = self.y.get().normalize(&values, draw_ctx);
        let w = self.width.get().normalize(&values, draw_ctx);
        let h = self.height.get().normalize(&values, draw_ctx);

        if mask_units == CoordUnits::ObjectBoundingBox {
            draw_ctx.pop_view_box();
        }

        // Use a scope because mask_cr needs to release the
        // reference to the surface before we access the pixels
        {
            let bbox_rect = {
                if let Some(ref rect) = draw_ctx.get_bbox().rect {
                    *rect
                } else {
                    // The node being masked is empty / doesn't have a
                    // bounding box, so there's nothing to mask!
                    return Ok(());
                }
            };

            let save_cr = draw_ctx.get_cairo_context();

            let mask_cr = cairo::Context::new(&surface);
            mask_cr.set_matrix(*affine_before_mask);
            mask_cr.transform(node.get_transform());

            draw_ctx.set_cairo_context(&mask_cr);

            if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.clip(
                    x * bbox_rect.width + bbox_rect.x,
                    y * bbox_rect.height + bbox_rect.y,
                    w * bbox_rect.width,
                    h * bbox_rect.height,
                );
            } else {
                draw_ctx.clip(x, y, w, h);
            }

            if content_units == CoordUnits::ObjectBoundingBox {
                let bbtransform = cairo::Matrix::new(
                    bbox_rect.width,
                    0.0,
                    0.0,
                    bbox_rect.height,
                    bbox_rect.x,
                    bbox_rect.y,
                );

                mask_cr.transform(bbtransform);

                draw_ctx.push_view_box(1.0, 1.0);
            }

            let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
                node.draw_children(&cascaded, dc, false)
            });

            if content_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.pop_view_box();
            }

            draw_ctx.set_cairo_context(&save_cr);

            res
        }?;

        let opacity = {
            let Opacity(o) = values.opacity;
            u8::from(o)
        };

        let mask_surface = compute_luminance_to_alpha(surface, opacity);

        let cr = draw_ctx.get_cairo_context();

        cr.identity_matrix();

        let (xofs, yofs) = draw_ctx.get_offset();
        cairo_mask_surface(&cr, &mask_surface, xofs, yofs);

        Ok(())
    }
}

// Takes a surface and overwrites the alpha channel of each pixel
// with the luminance of that pixel's RGB values.
fn compute_luminance_to_alpha(
    mut surface: cairo::ImageSurface,
    opacity: u8,
) -> cairo::ImageSurface {
    let width = surface.get_width();
    let rowstride = surface.get_stride() as usize;

    {
        let mut pixels = surface.get_data().unwrap();

        for row in pixels.chunks_mut(rowstride) {
            for p in row[..4 * width as usize].chunks_mut(4) {
                //  Assuming, the pixel is linear RGB (not sRGB)
                //  y = luminance
                //  Y = 0.2126 R + 0.7152 G + 0.0722 B
                //  1.0 opacity = 255
                //
                //  When Y = 1.0, pixel for mask should be 0xFFFFFFFF
                //    (you get 1.0 luminance from 255 from R, G and B)
                //
                // r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45  ~= 14042
                // g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69  ~= 47240
                // b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 =  4768.88  ~= 4769
                //
                // This allows for the following expected behaviour:
                //    (we only care about the most sig byte)
                // if pixel = 0x00FFFFFF, pixel' = 0xFF......
                // if pixel = 0x00020202, pixel' = 0x02......
                // if pixel = 0x00000000, pixel' = 0x00......
                //
                // NOTE: the following assumes little-endian
                let (r, g, b, o) = (p[2] as u32, p[1] as u32, p[0] as u32, opacity as u32);
                p[3] = (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8;
            }
        }
    }

    surface
}

impl NodeTrait for NodeMask {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(parse("x", value, LengthDir::Horizontal)?),
                Attribute::Y => self.y.set(parse("y", value, LengthDir::Vertical)?),
                Attribute::Width => self.width.set(parse_and_validate(
                    "width",
                    value,
                    LengthDir::Horizontal,
                    Length::check_nonnegative,
                )?),
                Attribute::Height => self.height.set(parse_and_validate(
                    "height",
                    value,
                    LengthDir::Vertical,
                    Length::check_nonnegative,
                )?),

                Attribute::MaskUnits => self.units.set(parse("maskUnits", value, ())?),

                Attribute::MaskContentUnits => {
                    self.content_units
                        .set(parse("maskContentUnits", value, ())?)
                }

                _ => (),
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Debug,Formatter,Result};
use value::{Value,ToValue};
use self::EveFn::*;
use value::Value::Float;

// Enums...
// Expression Enum ------------------------------------------------------------
#[derive(Clone)]
pub enum Expression {
	Constant(Constant),
	Variable(Variable),
	Call(Call),
	Match(Box<Match>),
	Value(Value),
}

impl Debug for Expression {

	fn fmt(&self, f: &mut Formatter) -> Result {
		match *self {
			Expression::Constant(ref x) => write!(f,"{:?}",*x),
			Expression::Call(ref x) => write!(f,"{:?}",*x),
			Expression::Variable(ref x) => write!(f,"{:?}",*x),
			Expression::Value(ref x) => write!(f,"{:?}",*x),
			Expression::Match(ref x) => write!(f,"{:?}",*x),
		}
	}
}

pub trait ToExpression { fn to_expr(self) -> Expression; }

impl ToExpression for Expression { fn to_expr(self) -> Expression { self } }
impl ToExpression for Call { fn to_expr(self) -> Expression { Expression::Call(self) } }
impl ToExpression for i32 { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl ToExpression for f64 { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl<'a> ToExpression for &'a str { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl ToExpression for Value { fn to_expr(self) -> Expression { Expression::Value(self) } }
impl ToExpression for Match { fn to_expr(self) -> Expression { Expression::Match( Box::new(self)) } }

// End Expression Enum --------------------------------------------------------

#[derive(Clone,Debug)]
pub enum EveFn {
	// Basic ops
	Add,Subtract,Multiply,Divide,Exponentiate,

	// General math
	Sqrt,Log,Log10,Log2,Ln,Abs,Sign,Exp,

	//Trig
	Sin,Cos,Tan,ASin,ACos,ATan,ATan2,

	// Aggregates
	Sum,Prod,

	// Strings
	StrConcat,StrUpper,StrLower,StrLength,StrReplace,StrSplit,
}

#[derive(Clone,Debug)]
pub struct Match {
	pub input: Expression,
	pub patterns: PatternVec,
	pub handlers: ExpressionVec,
}

// Begin Pattern Enum ---------------------------------------------------------
#[derive(Clone,Debug)]
pub enum Pattern {
	Constant(Constant),
	Variable(Variable),
	Tuple(PatternVec),
}

impl<'a> PartialEq<Value> for &'a Pattern {
	fn eq(&self, other: &Value) -> bool {
		match self {
			&&Pattern::Constant(ref x) => x == other,
			&&Pattern::Variable(_) => panic!("Cannot match Variable against Value"),
			&&Pattern::Tuple(_) => panic!("Cannot match Tuple against Value"),
		}
	}
}
// End Pattern Enum -----------------------------------------------------------

#[derive(Clone,Debug)]
pub struct Call {
	pub fun: EveFn,
	pub args: ExpressionVec,
}

// Some type aliases
pub type Constant = Value;
pub type Variable = String;
pub type PatternVec = Vec<Pattern>;
pub type ExpressionVec = Vec<Expression>;

// Macro for creating expression vectors
#[macro_export]
macro_rules! exprvec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = ExpressionVec::new();
            $(
                temp_vec.push($x.to_expr());
            )*
            temp_vec
        }
    };
}

// This is the main interface to the interpreter. Pass in an expression, get
// back a value
pub fn evaluate(e: & Expression) -> Value {

	eval_expression(e)

}

fn eval_expression(e: &Expression) -> Value {

	match *e {
		Expression::Call(ref x) => eval_call(x),
		Expression::Constant(ref x) => x.clone(),
		Expression::Value(ref x) => x.clone(),
		Expression::Match(ref x) => eval_match(x),
		_ => unimplemented!(),
	}
}

fn eval_match(m: &Match) -> Value {

	// Before we do anything, make sure we have the same number of patterns and
	// handlers
	assert_eq!(m.patterns.len(),m.handlers.len());

	let input = eval_expression(&m.input);
	let tests: Vec<Value> = m.patterns.iter()
						  			  .zip(m.handlers.iter())
						  			  .filter_map(|ph| -> Option<Value> {
													let (pattern,handler) = ph;
													if pattern == input { Some(eval_expression(&handler)) }
													else { None }
												})
						  			  .collect();

	Value::Tuple(tests)
}

fn eval_call(c: &Call) -> Value {

	let args: Vec<Value> = c.args.iter().map(eval_expression).collect();

	match(&c.fun, &args[..]) {

		// Basic Math
		(&Add,[Float(x),Float(y)]) => Float(x+y),
		(&Subtract,[Float(x),Float(y)]) => Float(x-y),
		(&Multiply,[Float(x),Float(y)]) => Float(x*y),
		(&Divide,[Float(x),Float(y)]) => {
			match (x,y) {
				(_,0f64) => panic!("Error: Division by 0"),
				(x,y) => Float(x/y),
			}
		},
		(&Exponentiate,[Float(x),Float(y)]) => Float(x.powf(y)),

		// Some general math functions
		(&Abs,[Float(x)]) => Float(x.abs()),
		(&Sqrt,[Float(x)]) => Float(x.sqrt()),
		(&Sign,[Float(x)]) => Float(x.signum()),
		(&Exp,[Float(x)]) => Float(x.exp()),
		(&Ln,[Float(x)]) => Float(x.ln()),
		(&Log10,[Float(x)]) => Float(x.log10()),
		(&Log2,[Float(x)]) => Float(x.log2()),

		// Trig functions
		(&Sin,[Float(x)]) => Float(x.sin()),
		(&Cos,[Float(x)]) => Float(x.cos()),
		(&Tan,[Float(x)]) => Float(x.tan()),
		(&ASin,[Float(x)]) => Float(x.asin()),
		(&ACos,[Float(x)]) => Float(x.acos()),
		(&ATan,[Float(x)]) => Float(x.atan()),
		(&ATan2,[Float(x),Float(y)]) => Float(x.atan2(y)),

		// String functions
		(&StrConcat,[Value::String(ref s1),Value::String(ref s2)]) => Value::String(s1.to_string()+&s2[..]),
		(&StrUpper,[Value::String(ref s)]) => Value::String(s.to_uppercase()),
		(&StrLower,[Value::String(ref s)]) => Value::String(s.to_lowercase()),
		(&StrLength,[Value::String(ref s)]) => Float(s.len() as f64),
		(&StrReplace,[Value::String(ref s),Value::String(ref q),Value::String(ref r)]) => Value::String(s.replace(&q[..],&r[..])),
		(&StrSplit,[Value::String(ref s)]) => {
			let w: Vec<Value> = s.words().map(|x| x.to_value()).collect();
			Value::Tuple(w)
		},

		// Aggregate functions
		//&Sum => general_agg(|x,y|{x+y},0f64,&c.args),
		//&Prod => general_agg(|x,y|{x*y},1f64,&c.args),

		// Returns an empty string for the purpose of handling incomplete function
		(_, _) => Value::String("".to_string()),
	}
}

/*
// Aggregate Functions --------------------------------------------------------

fn general_agg<F: Fn(f64,f64) -> f64>(f: F, base: f64, args: &ExpressionVec) -> Value {

	// Some fold magic!
	let acc = args.iter().fold(base,|acc,next_arg| f(acc,eval_expression(next_arg).to_f64().unwrap()) );

	acc.to_value()

}
// End Aggregate Functions ----------------------------------------------------
*/<commit_msg>Only take first match, added errors on invalid logarithm values<commit_after>use std::fmt::{Debug,Formatter,Result};
use value::{Value,ToValue};
use value;
use self::EveFn::*;
use value::Value::Float;

// Enums...
// Expression Enum ------------------------------------------------------------
#[derive(Clone)]
pub enum Expression {
	Constant(Constant),
	Variable(Variable),
	Call(Call),
	Match(Box<Match>),
	Value(Value),
}

impl Debug for Expression {

	fn fmt(&self, f: &mut Formatter) -> Result {
		match *self {
			Expression::Constant(ref x) => write!(f,"{:?}",*x),
			Expression::Call(ref x) => write!(f,"{:?}",*x),
			Expression::Variable(ref x) => write!(f,"{:?}",*x),
			Expression::Value(ref x) => write!(f,"{:?}",*x),
			Expression::Match(ref x) => write!(f,"{:?}",*x),
		}
	}
}

pub trait ToExpression { fn to_expr(self) -> Expression; }

impl ToExpression for Expression { fn to_expr(self) -> Expression { self } }
impl ToExpression for Call { fn to_expr(self) -> Expression { Expression::Call(self) } }
impl ToExpression for i32 { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl ToExpression for f64 { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl<'a> ToExpression for &'a str { fn to_expr(self) -> Expression { Expression::Value(self.to_value()) } }
impl ToExpression for Value { fn to_expr(self) -> Expression { Expression::Value(self) } }
impl ToExpression for Match { fn to_expr(self) -> Expression { Expression::Match( Box::new(self)) } }

// End Expression Enum --------------------------------------------------------

#[derive(Clone,Debug)]
pub enum EveFn {
	// Basic ops
	Add,Subtract,Multiply,Divide,Exponentiate,

	// General math
	Sqrt,Log,Log10,Log2,Ln,Abs,Sign,Exp,

	//Trig
	Sin,Cos,Tan,ASin,ACos,ATan,ATan2,

	// Aggregates
	Sum,Prod,

	// Strings
	StrConcat,StrUpper,StrLower,StrLength,StrReplace,StrSplit,
}

#[derive(Clone,Debug)]
pub struct Match {
	pub input: Expression,
	pub patterns: PatternVec,
	pub handlers: ExpressionVec,
}

// Begin Pattern Enum ---------------------------------------------------------
#[derive(Clone,Debug)]
pub enum Pattern {
	Constant(Constant),
	Variable(Variable),
	Tuple(PatternVec),
}

impl<'a> PartialEq<Value> for &'a Pattern {
	fn eq(&self, other: &Value) -> bool {
		match self {
			&&Pattern::Constant(ref x) => x == other,
			&&Pattern::Variable(_) => panic!("Cannot match Variable against Value"),
			&&Pattern::Tuple(_) => panic!("Cannot match Tuple against Value"),
		}
	}
}
// End Pattern Enum -----------------------------------------------------------

#[derive(Clone,Debug)]
pub struct Call {
	pub fun: EveFn,
	pub args: ExpressionVec,
}

// Some type aliases
pub type Constant = Value;
pub type Variable = String;
pub type PatternVec = Vec<Pattern>;
pub type ExpressionVec = Vec<Expression>;

// Macro for creating expression vectors
#[macro_export]
macro_rules! exprvec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = ExpressionVec::new();
            $(
                temp_vec.push($x.to_expr());
            )*
            temp_vec
        }
    };
}

// This is the main interface to the interpreter. Pass in an expression, get
// back a value
pub fn evaluate(e: & Expression) -> Value {

	eval_expression(e)

}

fn eval_expression(e: &Expression) -> Value {

	match *e {
		Expression::Call(ref x) => eval_call(x),
		Expression::Constant(ref x) => x.clone(),
		Expression::Value(ref x) => x.clone(),
		Expression::Match(ref x) => eval_match(x),
		_ => unimplemented!(),
	}
}

fn eval_match(m: &Match) -> Value {

	// Before we do anything, make sure we have the same number of patterns and
	// handlers
	assert_eq!(m.patterns.len(),m.handlers.len());

	let input = eval_expression(&m.input);
	let tests: Vec<Value> = m.patterns.iter()
						  			  .zip(m.handlers.iter())
						  			  .filter_map(|(pattern,handler)| -> Option<Value> {
													if pattern == input { Some(eval_expression(&handler)) }
													else { None }
												})
						  			  .take(1)
						  			  .collect();

	Value::Tuple(tests)
}

fn eval_call(c: &Call) -> Value {

	let args: Vec<Value> = c.args.iter().map(eval_expression).collect();

	match(&c.fun, &args[..]) {

		// Basic Math
		(&Add,[Float(x),Float(y)]) => Float(x+y),
		(&Subtract,[Float(x),Float(y)]) => Float(x-y),
		(&Multiply,[Float(x),Float(y)]) => Float(x*y),
		(&Divide,[Float(x),Float(y)]) => {
			match (x,y) {
				(_,0f64) => panic!("Error: Division by 0"),
				(x,y) => Float(x/y),
			}
		},
		(&Exponentiate,[Float(x),Float(y)]) => Float(x.powf(y)),

		// Some general math functions
		(&Abs,[Float(x)]) => Float(x.abs()),
		(&Sqrt,[Float(x)]) => Float(x.sqrt()),
		(&Sign,[Float(x)]) => Float(x.signum()),
		(&Exp,[Float(x)]) => Float(x.exp()),
		(&Ln,[Float(x)]) => {
			if x <= 0f64 {panic!("Error: ln(x<=0) is undefined")}
			else {Float(x.ln())}
		},
		(&Log10,[Float(x)]) => {
			if x <= 0f64 {panic!("Error: log10(x<=0) is undefined")}
			else {Float(x.log10())}
		},
		(&Log2,[Float(x)]) => {
			if x <= 0f64 {panic!("Error: log2(x<=0) is undefined")}
			else {Float(x.log2())}
		},

		// Trig functions
		(&Sin,[Float(x)]) => Float(x.sin()),
		(&Cos,[Float(x)]) => Float(x.cos()),
		(&Tan,[Float(x)]) => Float(x.tan()),
		(&ASin,[Float(x)]) => Float(x.asin()),
		(&ACos,[Float(x)]) => Float(x.acos()),
		(&ATan,[Float(x)]) => Float(x.atan()),
		(&ATan2,[Float(x),Float(y)]) => Float(x.atan2(y)),

		// String functions
		(&StrConcat,[Value::String(ref s1),Value::String(ref s2)]) => Value::String(s1.to_string()+&s2[..]),
		(&StrUpper,[Value::String(ref s)]) => Value::String(s.to_uppercase()),
		(&StrLower,[Value::String(ref s)]) => Value::String(s.to_lowercase()),
		(&StrLength,[Value::String(ref s)]) => Float(s.len() as f64),
		(&StrReplace,[Value::String(ref s),Value::String(ref q),Value::String(ref r)]) => Value::String(s.replace(&q[..],&r[..])),
		(&StrSplit,[Value::String(ref s)]) => {
			let w: Vec<Value> = s.words().map(|x| x.to_value()).collect();
			Value::Tuple(w)
		},

		// Aggregate functions
		(&Sum,[Value::Tuple(ref x)]) => general_agg(x),
		//&Prod => general_agg(|x,y|{x*y},1f64,&c.args),

		// Returns an empty string for the purpose of handling incomplete function
		(_, _) => Value::String("No Result".to_string()),
	}
}

/*
// Aggregate Functions --------------------------------------------------------

//fn general_agg<F: Fn(f64,f64) -> f64>(f: F, base: f64, args: &ExpressionVec) -> Value {
fn general_agg(x: &value::Tuple) -> Value {

	// Some fold magic!
	println!("{:?}",x);

	10f64.to_value()

}
// End Aggregate Functions ----------------------------------------------------
*/<|endoftext|>


<commit_before>use mongodb::{bson::doc, bson::Document, options::ClientOptions, Client};

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {

    // Parse your connection string into an options struct
    let mut client_options =
        ClientOptions::parse("mongodb://root:example@127.0.0.1:27017/admin?w=majority")
            .await?;

    // Manually set an option
    client_options.app_name = Some("Rust Demo".to_string());

    // Get a handle to the cluster
    let client = Client::with_options(client_options)?;

    // Ping the server to see if you can connect to the cluster
    client
        .database("admin")
        .run_command(doc! {"ping": 1}, None)
        .await?;
    println!("Connected successfully.");

    println!("Print all the db_names");
    // List the names of the databases in that cluster
    for db_name in client.list_database_names(None, None).await? {
        println!("{}", db_name);
    }

    println!("Adds something to a new db");

    let db = client.database("books");
    let collections = db.collection::<Document>("books");

    let docs = vec![
        doc! {"title": "123", "author":"potato"},
    ];

    collections.insert_many(docs, None).await?;

    Ok(())
}
<commit_msg>read better<commit_after>use mongodb::{
    bson::doc,
    bson::Document,
    options::ClientOptions, Client
};

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {

    // Parse your connection string into an options struct
    let mut client_options =
        ClientOptions::parse("mongodb://root:example@127.0.0.1:27017/admin?w=majority")
            .await?;

    // Manually set an option
    client_options.app_name = Some("Rust Demo".to_string());

    // Get a handle to the cluster
    let client = Client::with_options(client_options)?;

    // Ping the server to see if you can connect to the cluster
    client
        .database("admin")
        .run_command(doc! {"ping": 1}, None)
        .await?;
    println!("Connected successfully.");

    println!("Print all the db_names");
    // List the names of the databases in that cluster
    for db_name in client.list_database_names(None, None).await? {
        println!("{}", db_name);
    }

    println!("Adds something to a new db");

    let db = client.database("books");
    let collections = db.collection::<Document>("books");

    let docs = vec![
        doc! {"title": "123", "author":"potato"},
    ];

    collections.insert_many(docs, None).await?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate timely;
extern crate differential_dataflow;
extern crate dd_server;

use std::rc::Rc;
use std::cell::RefCell;

use timely::dataflow::operators::{Probe, Operator};
use differential_dataflow::operators::CountTotal;
use dd_server::{Environment, TraceHandle};

// load ./dataflows/degr_dist/target/release/libdegr_dist.dylib build <graph_name>

#[no_mangle]
pub fn build((dataflow, handles, probe, _timer, args): Environment) -> Result<(), String> {

    if args.len() != 1 { return Err(format!("expected one argument, instead: {:?}", args)); }

    let timer = _timer.clone();

    println!("{:?}: degree monitoring started", timer.elapsed());

    let mut delays = vec![0usize; 64];

    handles
        .get_mut::<Rc<RefCell<Option<TraceHandle>>>>(&args[0])?
        .borrow_mut().as_mut().unwrap()
        .import(dataflow)
        .as_collection(|k,v| (k.clone(), v.clone()))
        .map(|(src, _dst)| src as usize).count_total()
        .map(|(_src, cnt)| cnt as usize).count_total()
        // now we capture the observed latency on each record.
        .inner
        .unary(::timely::dataflow::channels::pact::Pipeline, "MeasureLatency", |_cap| {
            move |input, output| {

                let mut delays = [0usize; 64];

                let elapsed = timer.elapsed();
                let elapsed_ns = (elapsed.as_secs() as usize) * 1_000_000_000 + (elapsed.subsec_nanos() as usize);

                input.for_each(|cap, data| {
                    for &(_, ref time, _) in data.iter() {
                        let delay_ns = elapsed_ns - time.inner;
                        let bin = delay_ns.next_power_of_two().trailing_zeros() as usize;
                        delays[bin] += 1;
                    }
                    output.session(&cap).give(());
                });

                println!("delays (samples taking at most):");
                for i in 0 .. 64 {
                    if delays[i] > 0 {
                        println!("\t{}ns:\t{}", 1 << i, delays[i]);
                    }
                }
            }
        })
        .probe_with(probe);

    Ok(())
}<commit_msg>fix up reporting<commit_after>extern crate timely;
extern crate differential_dataflow;
extern crate dd_server;

use std::rc::Rc;
use std::cell::RefCell;

use timely::dataflow::operators::{Probe, Operator};
use differential_dataflow::operators::CountTotal;
use dd_server::{Environment, TraceHandle};

// load ./dataflows/degr_dist/target/release/libdegr_dist.dylib build <graph_name>

#[no_mangle]
pub fn build((dataflow, handles, probe, _timer, args): Environment) -> Result<(), String> {

    if args.len() != 1 { return Err(format!("expected one argument, instead: {:?}", args)); }

    let timer = _timer.clone();

    println!("{:?}: degree monitoring started", timer.elapsed());

    let mut delays = vec![0usize; 64];

    handles
        .get_mut::<Rc<RefCell<Option<TraceHandle>>>>(&args[0])?
        .borrow_mut().as_mut().unwrap()
        .import(dataflow)
        .as_collection(|k,v| (k.clone(), v.clone()))
        .map(|(src, _dst)| src as usize).count_total()
        .map(|(_src, cnt)| cnt as usize).count_total()
        // now we capture the observed latency on each record.
        .inner
        .unary(::timely::dataflow::channels::pact::Pipeline, "MeasureLatency", |_cap| {
            move |input, output| {

                let mut delays = [0usize; 64];

                let elapsed = timer.elapsed();
                let elapsed_ns = (elapsed.as_secs() as usize) * 1_000_000_000 + (elapsed.subsec_nanos() as usize);

                input.for_each(|cap, data| {
                    for &(_, ref time, _) in data.iter() {
                        let delay_ns = elapsed_ns - time.inner;
                        let bin = delay_ns.next_power_of_two().trailing_zeros() as usize;
                        delays[bin] += 1;
                    }
                    output.session(&cap).give(());
                });

                if delays.iter().any(|&x| x > 0) {
                    println!("delays (samples taking at most):");
                    for i in 0 .. 64 {
                        if delays[i] > 0 {
                            println!("\t{}ns:\t{}", 1u64 << i, delays[i]);
                        }
                    }
                }
            }
        })
        .probe_with(probe);

    Ok(())
}<|endoftext|>


<commit_before>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        // TODO: Remove?
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
//                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<commit_msg>Comment has been removed<commit_after>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        // TODO: Remove?
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<|endoftext|>


<commit_before>use std::ops::{Generator, GeneratorState};
use std::collections::{HashSet, HashMap};
use std::cell::RefCell;

use yield_instruction::YieldInstruction;

/// Unique identifier for a coroutine. After starting a corutine, use this to refer to that coroutine
pub struct CoroutineHandle(usize);

/// Conditions determining when to resume a coroutine. There are some pre-defined options, and a hook for defining a trait object with arbitrary logic
pub enum CoroutineCondition {
	WaitOneFrame,
	WaitForCoroutine(CoroutineHandle),
	YieldInstruction(Box<YieldInstruction>),
}

struct Coroutine {
	condition: CoroutineCondition,
	generator: Box<Generator<Yield=CoroutineCondition, Return=()>>,
}

struct CoroutineQueue {
	queued_coroutines: HashMap<usize, Box<Generator<Yield=CoroutineCondition, Return=()>>>,
	next_id: usize,
}
impl CoroutineQueue {
	fn new() -> Self {
		Self {
			queued_coroutines: HashMap::new(),
			next_id: 1,
		}
	}
	fn get_next_id(&mut self) -> usize {
		let next_id = self.next_id;
		self.next_id += 1;
		next_id
	}
}

struct CurrentCoroutines {
	current_coroutine_ids: HashSet<usize>,
	current_coroutines: HashMap<usize, Coroutine>,
}
impl CurrentCoroutines {
	fn new() -> Self {
		Self {
			current_coroutine_ids: HashSet::new(),
			current_coroutines: HashMap::new(),
		}
	}
	fn update(&mut self) {
		//for each coroutine, check if we should resume the coroutine, then check the yield vlaue to see if it's ended
		let mut finished_coroutines: Vec<usize> = Vec::new();
		for (id, coroutine) in self.current_coroutines.iter_mut() {
			let should_resume = match coroutine.condition {
				CoroutineCondition::WaitOneFrame => true,
				CoroutineCondition::WaitForCoroutine(CoroutineHandle(id)) => !self.current_coroutine_ids.contains(&id),
				CoroutineCondition::YieldInstruction(ref instruction) => instruction.should_resume(),
			};

			if should_resume {
				let resume_result = coroutine.generator.resume();

				match resume_result {
					GeneratorState::Yielded(condition) => {
						coroutine.condition = condition;
					}
					GeneratorState::Complete(()) => {
						finished_coroutines.push(*id)
					}
				}
			}
		}

		for id in finished_coroutines {
			self.current_coroutine_ids.remove(&id);
			self.current_coroutines.remove(&id);
		}
	}
}

/// CorputineManager manages the state and execution of several coroutines. Queue a new coroutine by calling start_coroutine(), and update all coroutines by calling update() once per frame
pub struct CoroutineManager {
	queue: RefCell<CoroutineQueue>,
	coroutines: RefCell<CurrentCoroutines>,
}
impl CoroutineManager {
	pub fn new() -> CoroutineManager {
		Self {
			queue: RefCell::new(CoroutineQueue::new()),
			coroutines: RefCell::new(CurrentCoroutines::new()),
		}
	}
	pub fn start_coroutine<G>(&self, coroutine: G) -> CoroutineHandle where G: Generator<Yield=CoroutineCondition, Return=()> + 'static {
		let mut queue_ref = self.queue.borrow_mut();

		let id = queue_ref.get_next_id();
		queue_ref.queued_coroutines.insert(id, Box::new(coroutine));

		CoroutineHandle(id)
	}
	pub fn update(&self) {
		let mut coroutine_ref = self.coroutines.borrow_mut();

		{
			//drain the queue of new coroutines into the list of active corutines
			//it's important to do this inside of an isolated scape, because coroutines may want to start new coroutines from within themselves
			//so the borrow on the queue must be released before we start updating the coroutines
			let mut queue_ref = self.queue.borrow_mut();
			for (k, generator) in queue_ref.queued_coroutines.drain() {
				coroutine_ref.current_coroutine_ids.insert(k);
				coroutine_ref.current_coroutines.insert(k, Coroutine { condition: CoroutineCondition::WaitOneFrame, generator});
			}
		}

		coroutine_ref.update();
	}
	pub fn has_coroutines(&self) -> bool {
		self.coroutines.borrow().current_coroutines.len() > 0 || self.queue.borrow().queued_coroutines.len() > 0
	}
}<commit_msg>Typo fixes<commit_after>use std::ops::{Generator, GeneratorState};
use std::collections::{HashSet, HashMap};
use std::cell::RefCell;

use yield_instruction::YieldInstruction;

/// Unique identifier for a coroutine. After starting a corutine, use this to refer to that coroutine
pub struct CoroutineHandle(usize);

/// Conditions determining when to resume a coroutine. There are some pre-defined options, and a hook for defining a trait object with arbitrary logic
pub enum CoroutineCondition {
	WaitOneFrame,
	WaitForCoroutine(CoroutineHandle),
	YieldInstruction(Box<YieldInstruction>),
}

struct Coroutine {
	condition: CoroutineCondition,
	generator: Box<Generator<Yield=CoroutineCondition, Return=()>>,
}

struct CoroutineQueue {
	queued_coroutines: HashMap<usize, Box<Generator<Yield=CoroutineCondition, Return=()>>>,
	next_id: usize,
}
impl CoroutineQueue {
	fn new() -> Self {
		Self {
			queued_coroutines: HashMap::new(),
			next_id: 1,
		}
	}
	fn get_next_id(&mut self) -> usize {
		let next_id = self.next_id;
		self.next_id += 1;
		next_id
	}
}

struct CurrentCoroutines {
	current_coroutine_ids: HashSet<usize>,
	current_coroutines: HashMap<usize, Coroutine>,
}
impl CurrentCoroutines {
	fn new() -> Self {
		Self {
			current_coroutine_ids: HashSet::new(),
			current_coroutines: HashMap::new(),
		}
	}
	fn update(&mut self) {
		//for each coroutine, check if we should resume the coroutine, then check the yield vlaue to see if it's ended
		let mut finished_coroutines: Vec<usize> = Vec::new();
		for (id, coroutine) in self.current_coroutines.iter_mut() {
			let should_resume = match coroutine.condition {
				CoroutineCondition::WaitOneFrame => true,
				CoroutineCondition::WaitForCoroutine(CoroutineHandle(id)) => !self.current_coroutine_ids.contains(&id),
				CoroutineCondition::YieldInstruction(ref instruction) => instruction.should_resume(),
			};

			if should_resume {
				let resume_result = coroutine.generator.resume();

				match resume_result {
					GeneratorState::Yielded(condition) => {
						coroutine.condition = condition;
					}
					GeneratorState::Complete(()) => {
						finished_coroutines.push(*id)
					}
				}
			}
		}

		for id in finished_coroutines {
			self.current_coroutine_ids.remove(&id);
			self.current_coroutines.remove(&id);
		}
	}
}

/// CoroutineManager manages the state and execution of several coroutines. Queue a new coroutine by calling start_coroutine(), and update all coroutines by calling update() once per frame
pub struct CoroutineManager {
	queue: RefCell<CoroutineQueue>,
	coroutines: RefCell<CurrentCoroutines>,
}
impl CoroutineManager {
	pub fn new() -> CoroutineManager {
		Self {
			queue: RefCell::new(CoroutineQueue::new()),
			coroutines: RefCell::new(CurrentCoroutines::new()),
		}
	}
	pub fn start_coroutine<G>(&self, coroutine: G) -> CoroutineHandle where G: Generator<Yield=CoroutineCondition, Return=()> + 'static {
		let mut queue_ref = self.queue.borrow_mut();

		let id = queue_ref.get_next_id();
		queue_ref.queued_coroutines.insert(id, Box::new(coroutine));

		CoroutineHandle(id)
	}
	pub fn update(&self) {
		let mut coroutine_ref = self.coroutines.borrow_mut();

		{
			//drain the queue of new coroutines into the hashmap of active coroutines
			//it's important to do this inside of an isolated scope, because coroutines may want to start new coroutines from within themselves
			//so the borrow on the queue must be released before we start updating the coroutines
			let mut queue_ref = self.queue.borrow_mut();
			for (k, generator) in queue_ref.queued_coroutines.drain() {
				coroutine_ref.current_coroutine_ids.insert(k);
				coroutine_ref.current_coroutines.insert(k, Coroutine { condition: CoroutineCondition::WaitOneFrame, generator});
			}
		}

		coroutine_ref.update();
	}
	pub fn has_coroutines(&self) -> bool {
		self.coroutines.borrow().current_coroutines.len() > 0 || self.queue.borrow().queued_coroutines.len() > 0
	}
}<|endoftext|>


<commit_before>/*!

An implementation of the Graph500 Breadth First Search problem in Rust.

*/

#[legacy_modes];

extern mod std;
use std::arc;
use std::time;
use std::map;
use std::map::Map;
use std::map::HashMap;
use std::deque;
use std::deque::Deque;
use std::par;
use io::WriterUtil;
use comm::*;
use int::abs;

type node_id = i64;
type graph = ~[~[node_id]];
type bfs_result = ~[node_id];

fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] {
    let r = rand::xorshift();

    fn choose_edge(i: node_id, j: node_id, scale: uint, r: rand::Rng)
        -> (node_id, node_id) {

        let A = 0.57;
        let B = 0.19;
        let C = 0.19;

        if scale == 0u {
            (i, j)
        }
        else {
            let i = i * 2i64;
            let j = j * 2i64;
            let scale = scale - 1u;

            let x = r.gen_float();

            if x < A {
                choose_edge(i, j, scale, r)
            }
            else {
                let x = x - A;
                if x < B {
                    choose_edge(i + 1i64, j, scale, r)
                }
                else {
                    let x = x - B;
                    if x < C {
                        choose_edge(i, j + 1i64, scale, r)
                    }
                    else {
                        choose_edge(i + 1i64, j + 1i64, scale, r)
                    }
                }
            }
        }
    }

    do vec::from_fn((1u << scale) * edgefactor) |_i| {
        choose_edge(0i64, 0i64, scale, r)
    }
}

fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph {
    let graph = do vec::from_fn(N) |_i| {
        map::HashMap::<node_id, ()>()
    };

    do vec::each(edges) |e| {
        let (i, j) = e;
        map::set_add(graph[i], j);
        map::set_add(graph[j], i);
        true
    }

    do graph.map() |v| {
        map::vec_from_set(v)
    }
}

fn gen_search_keys(graph: graph, n: uint) -> ~[node_id] {
    let keys = map::HashMap::<node_id, ()>();
    let r = rand::Rng();

    while keys.size() < n {
        let k = r.gen_uint_range(0u, graph.len());

        if graph[k].len() > 0u && vec::any(graph[k], |i| {
            i != k as node_id
        }) {
            map::set_add(keys, k as node_id);
        }
    }
    map::vec_from_set(keys)
}

/**
 * Returns a vector of all the parents in the BFS tree rooted at key.
 *
 * Nodes that are unreachable have a parent of -1.
 */
fn bfs(graph: graph, key: node_id) -> bfs_result {
    let marks : ~[mut node_id]
        = vec::to_mut(vec::from_elem(vec::len(graph), -1i64));

    let Q = deque::create();

    Q.add_back(key);
    marks[key] = key;

    while Q.size() > 0u {
        let t = Q.pop_front();

        do graph[t].each() |k| {
            if marks[k] == -1i64 {
                marks[k] = t;
                Q.add_back(k);
            }
            true
        };
    }

    vec::from_mut(marks)
}

/**
 * Another version of the bfs function.
 *
 * This one uses the same algorithm as the parallel one, just without
 * using the parallel vector operators.
 */
fn bfs2(graph: graph, key: node_id) -> bfs_result {
    // This works by doing functional updates of a color vector.

    enum color {
        white,
        // node_id marks which node turned this gray/black.
        // the node id later becomes the parent.
        gray(node_id),
        black(node_id)
    };

    let mut colors = do vec::from_fn(graph.len()) |i| {
        if i as node_id == key {
            gray(key)
        }
        else {
            white
        }
    };

    fn is_gray(c: color) -> bool {
        match c {
          gray(_) => { true }
          _ => { false }
        }
    }

    let mut i = 0u;
    while vec::any(colors, is_gray) {
        // Do the BFS.
        log(info, fmt!("PBFS iteration %?", i));
        i += 1u;
        colors = do colors.mapi() |i, c| {
            let c : color = c;
            match c {
              white => {
                let i = i as node_id;

                let neighbors = graph[i];

                let mut color = white;

                do neighbors.each() |k| {
                    if is_gray(colors[k]) {
                        color = gray(k);
                        false
                    }
                    else { true }
                };

                color
              }
              gray(parent) => { black(parent) }
              black(parent) => { black(parent) }
            }
        }
    }

    // Convert the results.
    do vec::map(colors) |c| {
        match c {
          white => { -1i64 }
          black(parent) => { parent }
          _ => { fail ~"Found remaining gray nodes in BFS" }
        }
    }
}

/// A parallel version of the bfs function.
fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
    // This works by doing functional updates of a color vector.

    enum color {
        white,
        // node_id marks which node turned this gray/black.
        // the node id later becomes the parent.
        gray(node_id),
        black(node_id)
    };

    let graph_vec = arc::get(&graph); // FIXME #3387 requires this temp
    let mut colors = do vec::from_fn(graph_vec.len()) |i| {
        if i as node_id == key {
            gray(key)
        }
        else {
            white
        }
    };

    #[inline(always)]
    fn is_gray(c: color) -> bool {
        match c {
          gray(_) => { true }
          _ => { false }
        }
    }

    let mut i = 0u;
    while par::any(colors, is_gray) {
        // Do the BFS.
        log(info, fmt!("PBFS iteration %?", i));
        i += 1u;
        let old_len = colors.len();

        let color = arc::ARC(colors);

        let color_vec = arc::get(&color); // FIXME #3387 requires this temp
        colors = do par::mapi_factory(*color_vec) {
            let colors = arc::clone(&color);
            let graph = arc::clone(&graph);
            fn~(i: uint, c: color) -> color {
                let c : color = c;
                let colors = arc::get(&colors);
                let graph = arc::get(&graph);
                match c {
                  white => {
                    let i = i as node_id;

                    let neighbors = graph[i];

                    let mut color = white;

                    do neighbors.each() |k| {
                        if is_gray(colors[k]) {
                            color = gray(k);
                            false
                        }
                        else { true }
                    };
                    color
                  }
                  gray(parent) => { black(parent) }
                  black(parent) => { black(parent) }
                }
            }
        };
        assert(colors.len() == old_len);
    }

    // Convert the results.
    do par::map(colors) |c| {
        match c {
          white => { -1i64 }
          black(parent) => { parent }
          _ => { fail ~"Found remaining gray nodes in BFS" }
        }
    }
}

/// Performs at least some of the validation in the Graph500 spec.
fn validate(edges: ~[(node_id, node_id)],
            root: node_id, tree: bfs_result) -> bool {
    // There are 5 things to test. Below is code for each of them.

    // 1. The BFS tree is a tree and does not contain cycles.
    //
    // We do this by iterating over the tree, and tracing each of the
    // parent chains back to the root. While we do this, we also
    // compute the levels for each node.

    log(info, ~"Verifying tree structure...");

    let mut status = true;
    let level = do tree.map() |parent| {
        let mut parent = parent;
        let mut path = ~[];

        if parent == -1i64 {
            // This node was not in the tree.
            -1
        }
        else {
            while parent != root {
                if vec::contains(path, parent) {
                    status = false;
                }

                vec::push(path, parent);
                parent = tree[parent];
            }

            // The length of the path back to the root is the current
            // level.
            path.len() as int
        }
    };

    if !status { return status }

    // 2. Each tree edge connects vertices whose BFS levels differ by
    //    exactly one.

    log(info, ~"Verifying tree edges...");

    let status = do tree.alli() |k, parent| {
        if parent != root && parent != -1i64 {
            level[parent] == level[k] - 1
        }
        else {
            true
        }
    };

    if !status { return status }

    // 3. Every edge in the input list has vertices with levels that
    //    differ by at most one or that both are not in the BFS tree.

    log(info, ~"Verifying graph edges...");

    let status = do edges.all() |e| {
        let (u, v) = e;

        abs(level[u] - level[v]) <= 1
    };

    if !status { return status }

    // 4. The BFS tree spans an entire connected component's vertices.

    // This is harder. We'll skip it for now...

    // 5. A node and its parent are joined by an edge of the original
    //    graph.

    log(info, ~"Verifying tree and graph edges...");

    let status = do par::alli(tree) |u, v| {
        let u = u as node_id;
        if v == -1i64 || u == root {
            true
        }
        else {
            edges.contains((u, v)) || edges.contains((v, u))
        }
    };

    if !status { return status }

    // If we get through here, all the tests passed!
    true
}

fn main(args: ~[~str]) {
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"15", ~"48"]
    } else if args.len() <= 1u {
        ~[~"", ~"10", ~"16"]
    } else {
        args
    };

    let scale = uint::from_str(args[1]).get();
    let num_keys = uint::from_str(args[2]).get();
    let do_validate = false;
    let do_sequential = true;

    let start = time::precise_time_s();
    let edges = make_edges(scale, 16u);
    let stop = time::precise_time_s();

    io::stdout().write_line(fmt!("Generated %? edges in %? seconds.",
                                 vec::len(edges), stop - start));

    let start = time::precise_time_s();
    let graph = make_graph(1u << scale, edges);
    let stop = time::precise_time_s();

    let mut total_edges = 0u;
    vec::each(graph, |edges| { total_edges += edges.len(); true });

    io::stdout().write_line(fmt!("Generated graph with %? edges in %? seconds.",
                                 total_edges / 2u,
                                 stop - start));

    let mut total_seq = 0.0;
    let mut total_par = 0.0;

    let graph_arc = arc::ARC(copy graph);

    do gen_search_keys(graph, num_keys).map() |root| {
        io::stdout().write_line(~"");
        io::stdout().write_line(fmt!("Search key: %?", root));

        if do_sequential {
            let start = time::precise_time_s();
            let bfs_tree = bfs(graph, root);
            let stop = time::precise_time_s();

            //total_seq += stop - start;

            io::stdout().write_line(
                fmt!("Sequential BFS completed in %? seconds.",
                     stop - start));

            if do_validate {
                let start = time::precise_time_s();
                assert(validate(edges, root, bfs_tree));
                let stop = time::precise_time_s();

                io::stdout().write_line(
                    fmt!("Validation completed in %? seconds.",
                         stop - start));
            }

            let start = time::precise_time_s();
            let bfs_tree = bfs2(graph, root);
            let stop = time::precise_time_s();

            total_seq += stop - start;

            io::stdout().write_line(
                fmt!("Alternate Sequential BFS completed in %? seconds.",
                     stop - start));

            if do_validate {
                let start = time::precise_time_s();
                assert(validate(edges, root, bfs_tree));
                let stop = time::precise_time_s();

                io::stdout().write_line(
                    fmt!("Validation completed in %? seconds.",
                         stop - start));
            }
        }

        let start = time::precise_time_s();
        let bfs_tree = pbfs(graph_arc, root);
        let stop = time::precise_time_s();

        total_par += stop - start;

        io::stdout().write_line(fmt!("Parallel BFS completed in %? seconds.",
                                     stop - start));

        if do_validate {
            let start = time::precise_time_s();
            assert(validate(edges, root, bfs_tree));
            let stop = time::precise_time_s();

            io::stdout().write_line(fmt!("Validation completed in %? seconds.",
                                         stop - start));
        }
    };

    io::stdout().write_line(~"");
    io::stdout().write_line(
        fmt!("Total sequential: %? \t Total Parallel: %? \t Speedup: %?x",
             total_seq, total_par, total_seq / total_par));
}
<commit_msg>Tweak graph500-bfs so it pretty-prints<commit_after>#[legacy_modes];

/*!

An implementation of the Graph500 Breadth First Search problem in Rust.

*/

extern mod std;
use std::arc;
use std::time;
use std::map;
use std::map::Map;
use std::map::HashMap;
use std::deque;
use std::deque::Deque;
use std::par;
use io::WriterUtil;
use comm::*;
use int::abs;

type node_id = i64;
type graph = ~[~[node_id]];
type bfs_result = ~[node_id];

fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] {
    let r = rand::xorshift();

    fn choose_edge(i: node_id, j: node_id, scale: uint, r: rand::Rng)
        -> (node_id, node_id) {

        let A = 0.57;
        let B = 0.19;
        let C = 0.19;

        if scale == 0u {
            (i, j)
        }
        else {
            let i = i * 2i64;
            let j = j * 2i64;
            let scale = scale - 1u;

            let x = r.gen_float();

            if x < A {
                choose_edge(i, j, scale, r)
            }
            else {
                let x = x - A;
                if x < B {
                    choose_edge(i + 1i64, j, scale, r)
                }
                else {
                    let x = x - B;
                    if x < C {
                        choose_edge(i, j + 1i64, scale, r)
                    }
                    else {
                        choose_edge(i + 1i64, j + 1i64, scale, r)
                    }
                }
            }
        }
    }

    do vec::from_fn((1u << scale) * edgefactor) |_i| {
        choose_edge(0i64, 0i64, scale, r)
    }
}

fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph {
    let graph = do vec::from_fn(N) |_i| {
        map::HashMap::<node_id, ()>()
    };

    do vec::each(edges) |e| {
        let (i, j) = e;
        map::set_add(graph[i], j);
        map::set_add(graph[j], i);
        true
    }

    do graph.map() |v| {
        map::vec_from_set(v)
    }
}

fn gen_search_keys(graph: graph, n: uint) -> ~[node_id] {
    let keys = map::HashMap::<node_id, ()>();
    let r = rand::Rng();

    while keys.size() < n {
        let k = r.gen_uint_range(0u, graph.len());

        if graph[k].len() > 0u && vec::any(graph[k], |i| {
            i != k as node_id
        }) {
            map::set_add(keys, k as node_id);
        }
    }
    map::vec_from_set(keys)
}

/**
 * Returns a vector of all the parents in the BFS tree rooted at key.
 *
 * Nodes that are unreachable have a parent of -1.
 */
fn bfs(graph: graph, key: node_id) -> bfs_result {
    let marks : ~[mut node_id]
        = vec::to_mut(vec::from_elem(vec::len(graph), -1i64));

    let Q = deque::create();

    Q.add_back(key);
    marks[key] = key;

    while Q.size() > 0u {
        let t = Q.pop_front();

        do graph[t].each() |k| {
            if marks[k] == -1i64 {
                marks[k] = t;
                Q.add_back(k);
            }
            true
        };
    }

    vec::from_mut(marks)
}

/**
 * Another version of the bfs function.
 *
 * This one uses the same algorithm as the parallel one, just without
 * using the parallel vector operators.
 */
fn bfs2(graph: graph, key: node_id) -> bfs_result {
    // This works by doing functional updates of a color vector.

    enum color {
        white,
        // node_id marks which node turned this gray/black.
        // the node id later becomes the parent.
        gray(node_id),
        black(node_id)
    };

    let mut colors = do vec::from_fn(graph.len()) |i| {
        if i as node_id == key {
            gray(key)
        }
        else {
            white
        }
    };

    fn is_gray(c: color) -> bool {
        match c {
          gray(_) => { true }
          _ => { false }
        }
    }

    let mut i = 0u;
    while vec::any(colors, is_gray) {
        // Do the BFS.
        log(info, fmt!("PBFS iteration %?", i));
        i += 1u;
        colors = do colors.mapi() |i, c| {
            let c : color = c;
            match c {
              white => {
                let i = i as node_id;

                let neighbors = graph[i];

                let mut color = white;

                do neighbors.each() |k| {
                    if is_gray(colors[k]) {
                        color = gray(k);
                        false
                    }
                    else { true }
                };

                color
              }
              gray(parent) => { black(parent) }
              black(parent) => { black(parent) }
            }
        }
    }

    // Convert the results.
    do vec::map(colors) |c| {
        match c {
          white => { -1i64 }
          black(parent) => { parent }
          _ => { fail ~"Found remaining gray nodes in BFS" }
        }
    }
}

/// A parallel version of the bfs function.
fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
    // This works by doing functional updates of a color vector.

    enum color {
        white,
        // node_id marks which node turned this gray/black.
        // the node id later becomes the parent.
        gray(node_id),
        black(node_id)
    };

    let graph_vec = arc::get(&graph); // FIXME #3387 requires this temp
    let mut colors = do vec::from_fn(graph_vec.len()) |i| {
        if i as node_id == key {
            gray(key)
        }
        else {
            white
        }
    };

    #[inline(always)]
    fn is_gray(c: color) -> bool {
        match c {
          gray(_) => { true }
          _ => { false }
        }
    }

    let mut i = 0u;
    while par::any(colors, is_gray) {
        // Do the BFS.
        log(info, fmt!("PBFS iteration %?", i));
        i += 1u;
        let old_len = colors.len();

        let color = arc::ARC(colors);

        let color_vec = arc::get(&color); // FIXME #3387 requires this temp
        colors = do par::mapi_factory(*color_vec) {
            let colors = arc::clone(&color);
            let graph = arc::clone(&graph);
            fn~(i: uint, c: color) -> color {
                let c : color = c;
                let colors = arc::get(&colors);
                let graph = arc::get(&graph);
                match c {
                  white => {
                    let i = i as node_id;

                    let neighbors = graph[i];

                    let mut color = white;

                    do neighbors.each() |k| {
                        if is_gray(colors[k]) {
                            color = gray(k);
                            false
                        }
                        else { true }
                    };
                    color
                  }
                  gray(parent) => { black(parent) }
                  black(parent) => { black(parent) }
                }
            }
        };
        assert(colors.len() == old_len);
    }

    // Convert the results.
    do par::map(colors) |c| {
        match c {
          white => { -1i64 }
          black(parent) => { parent }
          _ => { fail ~"Found remaining gray nodes in BFS" }
        }
    }
}

/// Performs at least some of the validation in the Graph500 spec.
fn validate(edges: ~[(node_id, node_id)],
            root: node_id, tree: bfs_result) -> bool {
    // There are 5 things to test. Below is code for each of them.

    // 1. The BFS tree is a tree and does not contain cycles.
    //
    // We do this by iterating over the tree, and tracing each of the
    // parent chains back to the root. While we do this, we also
    // compute the levels for each node.

    log(info, ~"Verifying tree structure...");

    let mut status = true;
    let level = do tree.map() |parent| {
        let mut parent = parent;
        let mut path = ~[];

        if parent == -1i64 {
            // This node was not in the tree.
            -1
        }
        else {
            while parent != root {
                if vec::contains(path, parent) {
                    status = false;
                }

                vec::push(path, parent);
                parent = tree[parent];
            }

            // The length of the path back to the root is the current
            // level.
            path.len() as int
        }
    };

    if !status { return status }

    // 2. Each tree edge connects vertices whose BFS levels differ by
    //    exactly one.

    log(info, ~"Verifying tree edges...");

    let status = do tree.alli() |k, parent| {
        if parent != root && parent != -1i64 {
            level[parent] == level[k] - 1
        }
        else {
            true
        }
    };

    if !status { return status }

    // 3. Every edge in the input list has vertices with levels that
    //    differ by at most one or that both are not in the BFS tree.

    log(info, ~"Verifying graph edges...");

    let status = do edges.all() |e| {
        let (u, v) = e;

        abs(level[u] - level[v]) <= 1
    };

    if !status { return status }

    // 4. The BFS tree spans an entire connected component's vertices.

    // This is harder. We'll skip it for now...

    // 5. A node and its parent are joined by an edge of the original
    //    graph.

    log(info, ~"Verifying tree and graph edges...");

    let status = do par::alli(tree) |u, v| {
        let u = u as node_id;
        if v == -1i64 || u == root {
            true
        }
        else {
            edges.contains((u, v)) || edges.contains((v, u))
        }
    };

    if !status { return status }

    // If we get through here, all the tests passed!
    true
}

fn main(args: ~[~str]) {
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"15", ~"48"]
    } else if args.len() <= 1u {
        ~[~"", ~"10", ~"16"]
    } else {
        args
    };

    let scale = uint::from_str(args[1]).get();
    let num_keys = uint::from_str(args[2]).get();
    let do_validate = false;
    let do_sequential = true;

    let start = time::precise_time_s();
    let edges = make_edges(scale, 16u);
    let stop = time::precise_time_s();

    io::stdout().write_line(fmt!("Generated %? edges in %? seconds.",
                                 vec::len(edges), stop - start));

    let start = time::precise_time_s();
    let graph = make_graph(1u << scale, edges);
    let stop = time::precise_time_s();

    let mut total_edges = 0u;
    vec::each(graph, |edges| { total_edges += edges.len(); true });

    io::stdout().write_line(fmt!("Generated graph with %? edges in %? seconds.",
                                 total_edges / 2u,
                                 stop - start));

    let mut total_seq = 0.0;
    let mut total_par = 0.0;

    let graph_arc = arc::ARC(copy graph);

    do gen_search_keys(graph, num_keys).map() |root| {
        io::stdout().write_line(~"");
        io::stdout().write_line(fmt!("Search key: %?", root));

        if do_sequential {
            let start = time::precise_time_s();
            let bfs_tree = bfs(graph, root);
            let stop = time::precise_time_s();

            //total_seq += stop - start;

            io::stdout().write_line(
                fmt!("Sequential BFS completed in %? seconds.",
                     stop - start));

            if do_validate {
                let start = time::precise_time_s();
                assert(validate(edges, root, bfs_tree));
                let stop = time::precise_time_s();

                io::stdout().write_line(
                    fmt!("Validation completed in %? seconds.",
                         stop - start));
            }

            let start = time::precise_time_s();
            let bfs_tree = bfs2(graph, root);
            let stop = time::precise_time_s();

            total_seq += stop - start;

            io::stdout().write_line(
                fmt!("Alternate Sequential BFS completed in %? seconds.",
                     stop - start));

            if do_validate {
                let start = time::precise_time_s();
                assert(validate(edges, root, bfs_tree));
                let stop = time::precise_time_s();

                io::stdout().write_line(
                    fmt!("Validation completed in %? seconds.",
                         stop - start));
            }
        }

        let start = time::precise_time_s();
        let bfs_tree = pbfs(graph_arc, root);
        let stop = time::precise_time_s();

        total_par += stop - start;

        io::stdout().write_line(fmt!("Parallel BFS completed in %? seconds.",
                                     stop - start));

        if do_validate {
            let start = time::precise_time_s();
            assert(validate(edges, root, bfs_tree));
            let stop = time::precise_time_s();

            io::stdout().write_line(fmt!("Validation completed in %? seconds.",
                                         stop - start));
        }
    };

    io::stdout().write_line(~"");
    io::stdout().write_line(
        fmt!("Total sequential: %? \t Total Parallel: %? \t Speedup: %?x",
             total_seq, total_par, total_seq / total_par));
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;
use websocket::WebSocketError;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::time::Duration;
use std::thread;
use std::rc::Rc;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let read_channel_out = Rc::new(read_channel_out);
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let write_channel_out = Rc::new(write_channel_out);
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream);
                    write_channel_out.send(sink);
                    Ok(())
                });
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let read_handler = pool.spawn_fn(move || {
        let state_read = state_read.clone();
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            stream.for_each(move |msg|{
                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                    Ok(())
            }).map_err(|_| ())
        })
    });
    let state_write = state.clone();
    let write_handler = pool.spawn_fn(move || {
        let state_write = state.clone();
        write_channel_in.for_each(move |sink| {
            let state_write = state.clone();
            future::loop_fn(sink, move |sink| {
                thread::sleep(Duration::from_secs(4));
                send(&state_write.read().unwrap(), sink)
                    .map(|sink| {
                        match 1 {
                            1 => Loop::Continue(sink),
                            _ => Loop::Break(())
                        }
                    })
            }).map_err(|_| ())
        })
    });
    let handlers = connection_handler.join3(read_handler, write_handler);
    core.run(handlers).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type SplitSink = futures::stream::SplitSink<
                    websocket::client::async::Framed<tokio_core::net::TcpStream,
                    websocket::async::MessageCodec<websocket::OwnedMessage>>
                >;

fn send(state: &State, sink: SplitSink) -> futures::sink::Send<SplitSink> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    sink.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<commit_msg>Core: Fix syntax errors<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::time::Duration;
use std::thread;
use std::rc::Rc;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            let handle_inner = handle.clone();
            let f = upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    let f = read_channel_out.send(stream);
                    spawn_future(f, "Register client listener", &handle_inner);
                    let f = write_channel_out.send(sink);
                    spawn_future(f, "Register client listener", &handle_inner);
                    Ok(())
                });
            spawn_future(f, "Client Connections", &handle);
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let read_handler = pool.spawn_fn(move || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            stream.for_each(move |msg|{
                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                    Ok(())
            }).map_err(|_| ())
        })
    });
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let state_write = state.clone();
            future::loop_fn(sink, move |sink| {
                thread::sleep(Duration::from_secs(4));
                send(&state_write.read().unwrap(), sink)
                    .map(|sink| {
                        match 1 {
                            1 => Loop::Continue(sink),
                            _ => Loop::Break(())
                        }
                    })
            }).map_err(|_| ())
        })
    });
    let handlers = connection_handler.join3(read_handler, write_handler);

    core.run(handlers).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type SplitSink = futures::stream::SplitSink<
                    websocket::client::async::Framed<tokio_core::net::TcpStream,
                    websocket::async::MessageCodec<websocket::OwnedMessage>>
                >;

fn send(state: &State, sink: SplitSink) -> futures::sink::Send<SplitSink> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    sink.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<|endoftext|>


<commit_before>use std::convert::Into;
generate_error_imports!();

generate_custom_error_types!(HookError, HookErrorKind, CustomData,
    HookExecutionError  => "Hook exec error",
    AccessTypeViolation => "Hook access type violation",
    MutableHooksNotAllowed => "Mutable Hooks are denied"
);

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
pub struct CustomData {
    aborting: bool,
}

impl HookError {

    pub fn is_aborting(&self) -> bool {
        match self.custom_data {
            Some(b) => b.aborting,
            None => true
        }
    }

}
<commit_msg>Add interface for custom error data type<commit_after>use std::convert::Into;
use std::default::Default;

generate_error_imports!();

generate_custom_error_types!(HookError, HookErrorKind, CustomData,
    HookExecutionError  => "Hook exec error",
    AccessTypeViolation => "Hook access type violation",
    MutableHooksNotAllowed => "Mutable Hooks are denied"
);

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
pub struct CustomData {
    aborting: bool,
}

impl CustomData {

    pub fn aborting(mut self, b: bool) -> CustomData {
        self.aborting = b;
        self
    }

}

impl Default for CustomData {

    fn default() -> CustomData {
        CustomData {
            aborting: true
        }
    }

}

impl HookError {

    pub fn is_aborting(&self) -> bool {
        match self.custom_data {
            Some(b) => b.aborting,
            None => true
        }
    }

}
<|endoftext|>