<commit_before>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::Into;

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T>(x: T, y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T>(x: T, y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Root type

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

// Main categories

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

// Function codes

#[derive(Debug)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug)]
pub enum Operation {
    Interpolate(Coordinates, Option<CoordinateOffset>),
    Move(Coordinates),
    Flash(Coordinates),
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    use super::{Command, FunctionCode, GCode};

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

}
<commit_msg>Allow mixed types in CoordinateNumber::new / CoordinateFormat::new<commit_after>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::Into;

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Root type

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

// Main categories

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

// Function codes

#[derive(Debug)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug)]
pub enum Operation {
    Interpolate(Coordinates, Option<CoordinateOffset>),
    Move(Coordinates),
    Flash(Coordinates),
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    extern crate conv;

    use conv::TryFrom;
    use super::*;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_coordinates_into() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), CoordinateNumber::from(2), cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_coordinates_into_mixed() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), 2, cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

}
<|endoftext|>


<commit_before>// Copyright 2016 Gomez Guillaume
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::{Debug, Display, Error, Formatter};
use std::cmp::PartialEq;
use std::ops::Deref;
use std::borrow::Borrow;

pub const OUTPUT_COMMENT_FILE : &'static str = "comments.cmts";

pub struct ParseResult {
    pub event_list: Vec<EventInfo>,
    pub comment_lines: Vec<usize>,
    pub original_content : Vec<String>,
}

pub struct EventInfo {
    pub line: usize,
    pub event: EventType,
}

impl EventInfo {
    pub fn new(line: usize, event: EventType) -> EventInfo {
        EventInfo {
            line: line,
            event: event,
        }
    }
}

impl Debug for EventInfo {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self.event {
            EventType::Type(ref t) => { writeln!(fmt, "{:?}->{:?}", self.line, t) }
            _ => Ok(())
        }
    }
}

pub enum EventType {
    Comment(String),
    FileComment(String),
    Type(TypeStruct),
    InScope,
    OutScope,
}

impl Debug for EventType {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &EventType::Type(ref t) => writeln!(fmt, "{:?}", t),
            _ => Ok(())
        }
    }
}

pub struct TypeStruct {
    pub ty: Type,
    pub parent: Option<Box<TypeStruct>>,
    pub name: String,
    pub args: Vec<String>,
}

impl TypeStruct {
    pub fn new(ty: Type, name: &str) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: name.to_owned(),
            args: vec!(),
            parent: None,
        }
    }

    /*pub fn from_args(ty: Type, args: Vec<String>) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: String::new(),
            args: args,
            parent: None,
        }
    }*/

    pub fn empty() -> TypeStruct {
        TypeStruct {
            ty: Type::Unknown,
            name: String::new(),
            args: Vec::new(),
            parent: None,
        }
    }

    pub fn get_depth(&self, ignore_macros: bool) -> usize {
        fn recur(ty: &Option<Box<TypeStruct>>, is_parent: bool, ignore_macros: bool) -> usize {
            match ty {
                &Some(ref t) => {
                    if ignore_macros && is_parent && t.ty == Type::Macro {
                        recur(&t.parent, true, ignore_macros)
                    } else {
                        recur(&t.parent, true, ignore_macros) + 1
                    }
                },
                _ => 0,
            }
        }
        recur(&self.parent, false, ignore_macros)
    }
}

impl PartialEq for TypeStruct {
    fn eq(&self, other: &TypeStruct) -> bool {
        self.ty == other.ty &&
        self.name == other.name &&
        self.args == other.args &&
        self.parent == other.parent
    }

    fn ne(&self, other: &TypeStruct) -> bool {
        !self.eq(other)
    }
}

impl Clone for TypeStruct {
    fn clone(&self) -> TypeStruct {
        TypeStruct {
            ty: self.ty,
            name: self.name.clone(),
            args: self.args.clone(),
            parent: match self.parent {
                Some(ref p) => Some(Box::new(p.deref().clone())),
                None => None,
            }
        }
    }

    fn clone_from(&mut self, source: &TypeStruct) {
        self.ty = source.ty;
        self.name = source.name.clone();
        self.args = source.args.clone();
        self.parent = match source.parent {
            Some(ref p) => Some(Box::new(p.deref().clone())),
            None => None,
        };
    }
}

impl Debug for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let parent = &self.parent;
        match parent {
            &Some(ref p) => write!(f, "{:?}§{} {}{}", p, self.ty, self.name, self.args.join(" ")),
            _ => write!(f, "{} {}{}", self.ty, self.name, self.args.join(" ")),
        }
    }
}

fn show(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
    if is_parent {
        write!(f, "{} {}{}§", t.ty, t.name, t.args.join(" "))
    } else {
        write!(f, "{} {}{}", t.ty, t.name, t.args.join(" "))
    }
}

fn sub_call(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
    if t.ty == Type::Macro && is_parent == true {
        match t.parent {
            Some(ref p) => sub_call(f, p.borrow(), true),
            _ => Ok(()),
        }
    } else {
        match t.parent {
            Some(ref p) => {
                try!(sub_call(f, p.borrow(), true));
                show(f, t, is_parent)
            },
            _ => show(f, t, is_parent),
        }
    }
}

impl Display for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        sub_call(f, self, false)
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Type {
    Struct,
    Mod,
    Enum,
    Fn,
    Const,
    Static,
    Type,
    Variant,
    Impl,
    Use,
    Macro,
    Trait,
    Unknown,
}

impl Type {
    pub fn from(s: &str) -> Type {
        match s {
            "struct" => Type::Struct,
            "mod" => Type::Mod,
            "enum" => Type::Enum,
            "fn" => Type::Fn,
            "const" => Type::Const,
            "static" => Type::Static,
            "type" => Type::Type,
            "impl" => Type::Impl,
            "use" => Type::Use,
            "trait" => Type::Trait,
            "macro" | "macro_rules" | "macro_rules!" => Type::Macro,
            _ => Type::Variant,
        }
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            Type::Struct => write!(f, "struct"),
            Type::Mod => write!(f, "mod"),
            Type::Enum => write!(f, "enum"),
            Type::Fn => write!(f, "fn"),
            Type::Const => write!(f, "const"),
            Type::Static => write!(f, "static"),
            Type::Type => write!(f, "type"),
            Type::Variant => write!(f, "variant"),
            Type::Impl => write!(f, "impl"),
            Type::Use => write!(f, "use"),
            Type::Trait => write!(f, "trait"),
            Type::Macro => write!(f, "macro"),
            _ => write!(f, "?"),
        }
    }
}
<commit_msg>Remove useless trait function reimplementations<commit_after>// Copyright 2016 Gomez Guillaume
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::{Debug, Display, Error, Formatter};
use std::cmp::PartialEq;
use std::ops::Deref;
use std::borrow::Borrow;

pub const OUTPUT_COMMENT_FILE : &'static str = "comments.cmts";

pub struct ParseResult {
    pub event_list: Vec<EventInfo>,
    pub comment_lines: Vec<usize>,
    pub original_content : Vec<String>,
}

pub struct EventInfo {
    pub line: usize,
    pub event: EventType,
}

impl EventInfo {
    pub fn new(line: usize, event: EventType) -> EventInfo {
        EventInfo {
            line: line,
            event: event,
        }
    }
}

impl Debug for EventInfo {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self.event {
            EventType::Type(ref t) => { writeln!(fmt, "{:?}->{:?}", self.line, t) }
            _ => Ok(())
        }
    }
}

pub enum EventType {
    Comment(String),
    FileComment(String),
    Type(TypeStruct),
    InScope,
    OutScope,
}

impl Debug for EventType {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &EventType::Type(ref t) => writeln!(fmt, "{:?}", t),
            _ => Ok(())
        }
    }
}

pub struct TypeStruct {
    pub ty: Type,
    pub parent: Option<Box<TypeStruct>>,
    pub name: String,
    pub args: Vec<String>,
}

impl TypeStruct {
    pub fn new(ty: Type, name: &str) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: name.to_owned(),
            args: vec!(),
            parent: None,
        }
    }

    /*pub fn from_args(ty: Type, args: Vec<String>) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: String::new(),
            args: args,
            parent: None,
        }
    }*/

    pub fn empty() -> TypeStruct {
        TypeStruct {
            ty: Type::Unknown,
            name: String::new(),
            args: Vec::new(),
            parent: None,
        }
    }

    pub fn get_depth(&self, ignore_macros: bool) -> usize {
        fn recur(ty: &Option<Box<TypeStruct>>, is_parent: bool, ignore_macros: bool) -> usize {
            match ty {
                &Some(ref t) => {
                    if ignore_macros && is_parent && t.ty == Type::Macro {
                        recur(&t.parent, true, ignore_macros)
                    } else {
                        recur(&t.parent, true, ignore_macros) + 1
                    }
                },
                _ => 0,
            }
        }
        recur(&self.parent, false, ignore_macros)
    }
}

impl PartialEq for TypeStruct {
    fn eq(&self, other: &TypeStruct) -> bool {
        self.ty == other.ty &&
        self.name == other.name &&
        self.args == other.args &&
        self.parent == other.parent
    }
}

impl Clone for TypeStruct {
    fn clone(&self) -> TypeStruct {
        TypeStruct {
            ty: self.ty,
            name: self.name.clone(),
            args: self.args.clone(),
            parent: match self.parent {
                Some(ref p) => Some(Box::new(p.deref().clone())),
                None => None,
            }
        }
    }
}

impl Debug for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let parent = &self.parent;
        match parent {
            &Some(ref p) => write!(f, "{:?}§{} {}{}", p, self.ty, self.name, self.args.join(" ")),
            _ => write!(f, "{} {}{}", self.ty, self.name, self.args.join(" ")),
        }
    }
}

fn show(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
    if is_parent {
        write!(f, "{} {}{}§", t.ty, t.name, t.args.join(" "))
    } else {
        write!(f, "{} {}{}", t.ty, t.name, t.args.join(" "))
    }
}

fn sub_call(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
    if t.ty == Type::Macro && is_parent == true {
        match t.parent {
            Some(ref p) => sub_call(f, p.borrow(), true),
            _ => Ok(()),
        }
    } else {
        match t.parent {
            Some(ref p) => {
                try!(sub_call(f, p.borrow(), true));
                show(f, t, is_parent)
            },
            _ => show(f, t, is_parent),
        }
    }
}

impl Display for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        sub_call(f, self, false)
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Type {
    Struct,
    Mod,
    Enum,
    Fn,
    Const,
    Static,
    Type,
    Variant,
    Impl,
    Use,
    Macro,
    Trait,
    Unknown,
}

impl Type {
    pub fn from(s: &str) -> Type {
        match s {
            "struct" => Type::Struct,
            "mod" => Type::Mod,
            "enum" => Type::Enum,
            "fn" => Type::Fn,
            "const" => Type::Const,
            "static" => Type::Static,
            "type" => Type::Type,
            "impl" => Type::Impl,
            "use" => Type::Use,
            "trait" => Type::Trait,
            "macro" | "macro_rules" | "macro_rules!" => Type::Macro,
            _ => Type::Variant,
        }
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            Type::Struct => write!(f, "struct"),
            Type::Mod => write!(f, "mod"),
            Type::Enum => write!(f, "enum"),
            Type::Fn => write!(f, "fn"),
            Type::Const => write!(f, "const"),
            Type::Static => write!(f, "static"),
            Type::Type => write!(f, "type"),
            Type::Variant => write!(f, "variant"),
            Type::Impl => write!(f, "impl"),
            Type::Use => write!(f, "use"),
            Type::Trait => write!(f, "trait"),
            Type::Macro => write!(f, "macro"),
            _ => write!(f, "?"),
        }
    }
}
<|endoftext|>


<commit_before>/// Macro for easily creating block classes
///
/// ## NOTE:
/// The Type enum must have a Block subtype like this:
/// ```
/// enum Type {
///     ....,
///     Block,
/// }
/// ```
/// and the Message must have a None subtype like this:
/// ```
/// enum Message {
///     ....,
///     None,
/// }
/// ```
///
/// ## Example:
/// ```
/// block! {
///     Type: ActorType,
///     Message: ActorMessage:
///     Blocks: {
///         block {
///             name: GrassBlock, // the name of the block
///             path: "assets/spritesheet.png", // the path of the spritesheet
///             index: 20, // the sprite index inside the spritesheet
///             width: 5, // width of block
///             height: 5, // height of block
///             sprites_in_row: 10, // number of blocks in the spritesheet in a row
///             size: 20, // size of the rendered block
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! block {
    (
        actor_type: $actor_type:ident,
        actor_message: $actor_message:ident,
        blocks: {
            $(
                block {
                    name: $name:ident,
                    path: $path:expr,
                    index: $index:expr,
                    width: $width:expr,
                    height: $height:expr,
                    sprites_in_row: $sprites_in_row:expr,
                    size: $size:expr,
                    collision_filter: $filter:expr
                }
            )*
        }
    ) => {
        $(
            pub struct $name {
                id: i32,
                pub rect: ::engine::SpriteRectangle,
                pub sprite: ::engine::Sprite,
            }

            impl $name {
                pub fn new(id: i32,
                           position: (i32, i32),
                           renderer: &mut ::sdl2::render::Renderer,
                           _fps: f64)
                    -> $name {
                        let anim_data = ::engine::AnimationData {
                            width: $width,
                            height: $height,
                            sprites_in_row: $sprites_in_row,
                            path: $path,
                        };

                        let anim = ::engine::Animation::new(anim_data, renderer);
                        let mut sprite_anims = anim.range($index, $index + 1);
                        let sprite = sprite_anims.pop().unwrap();

                        $name {
                            id: id,
                            rect: ::engine::SpriteRectangle::new(position.0,
                                                       position.1,
                                                       $size,
                                                       $size),
                                                       sprite: sprite,
                        }
                    }
            }

            impl ::engine::Actor<$actor_type, $actor_message> for $name {
                fn handle_message(&mut self, _: &$actor_message) -> $actor_message {
                    $actor_message::None
                }

                #[allow(unused_imports)]
                fn collides_with(&mut self,
                                 other_actor: &::engine::ActorData<$actor_type>)
                    -> Option<::engine::CollisionSide> {
                        use ::engine::Collision;
                        self.rect.collides_with(other_actor.rect)
                    }

                fn update(&mut self,
                          _context: &mut ::engine::Context,
                          _elapsed: f64)
                    -> ::engine::PositionChange {
                        ::engine::PositionChange::new()
                    }

                #[allow(unused_imports)]
                fn render(&mut self,
                          context: &mut ::engine::Context,
                          viewport: &mut ::engine::Viewport,
                          _elapsed: f64) {
                    use ::engine::Renderable;
                    let (rx, ry) = viewport.relative_point((self.rect.x, self.rect.y));
                    let rect = ::sdl2::rect::Rect::new_unwrap(rx, ry, self.rect.w, self.rect.h);

                    self.sprite.render(&mut context.renderer, rect);
                }

                fn data(&mut self) -> ::engine::ActorData<$actor_type> {
                    ::engine::ActorData {
                        id: self.id,
                        state: 0 as u32,
                        damage: 0,
                        resolves_collisions: false,
                        collision_filter: $filter,
                        rect: self.rect.to_sdl().unwrap(),
                        bounding_box: Some(::engine::BoundingBox::Rectangle(self.rect.clone())),
                        actor_type: $actor_type::Block,
                    }
                }

                fn change_pos(&mut self, _: &::engine::PositionChange) {}
            }
        )*
    }
}
<commit_msg>Fixed documentation typo<commit_after>/// Macro for easily creating block classes
///
/// ## NOTE:
/// The Type enum must have a Block subtype like this:
/// ```
/// enum Type {
///     ....,
///     Block,
/// }
/// ```
/// and the Message must have a None subtype like this:
/// ```
/// enum Message {
///     ....,
///     None,
/// }
/// ```
///
/// ## Example:
/// ```
/// block! {
///     actor_type: ActorType,
///     actor_message: ActorMessage,
///     blocks: {
///         block {
///             name: GrassBlock, // the name of the block
///             path: "assets/spritesheet.png", // the path of the spritesheet
///             index: 20, // the sprite index inside the spritesheet
///             width: 5, // width of block
///             height: 5, // height of block
///             sprites_in_row: 10, // number of blocks in the spritesheet in a row
///             size: 20, // size of the rendered block
///         }
///
///         block {
///             ....
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! block {
    (
        actor_type: $actor_type:ident,
        actor_message: $actor_message:ident,
        blocks: {
            $(
                block {
                    name: $name:ident,
                    path: $path:expr,
                    index: $index:expr,
                    width: $width:expr,
                    height: $height:expr,
                    sprites_in_row: $sprites_in_row:expr,
                    size: $size:expr,
                    collision_filter: $filter:expr
                }
            )*
        }
    ) => {
        $(
            pub struct $name {
                pub rect: ::engine::SpriteRectangle,
                pub sprite: ::engine::Sprite,
                id: i32,
            }

            impl $name {
                pub fn new(id: i32,
                           position: (i32, i32),
                           renderer: &mut ::sdl2::render::Renderer,
                           _fps: f64)
                           -> $name {
                    let anim_data = ::engine::AnimationData {
                        width: $width,
                        height: $height,
                        sprites_in_row: $sprites_in_row,
                        path: $path,
                    };

                    let anim = ::engine::Animation::new(anim_data, renderer);
                    let mut sprite_anims = anim.range($index, $index + 1);
                    let sprite = sprite_anims.pop().unwrap();

                    $name {
                        id: id,
                        rect: ::engine::SpriteRectangle::new(position.0,
                                                             position.1,
                                                             $size,
                                                             $size),
                        sprite: sprite,
                    }
                }
            }

            impl ::engine::Actor<$actor_type, $actor_message> for $name {
                fn handle_message(&mut self, _: &$actor_message) -> $actor_message {
                    $actor_message::None
                }

                #[allow(unused_imports)]
                fn collides_with(&mut self,
                                 other_actor: &::engine::ActorData<$actor_type>)
                                 -> Option<::engine::CollisionSide> {
                    use ::engine::Collision;
                    self.rect.collides_with(other_actor.rect)
                }

                fn update(&mut self,
                          _context: &mut ::engine::Context,
                          _elapsed: f64)
                          -> ::engine::PositionChange {
                    ::engine::PositionChange::new()
                }

                #[allow(unused_imports)]
                fn render(&mut self,
                          context: &mut ::engine::Context,
                          viewport: &mut ::engine::Viewport,
                          _elapsed: f64) {
                    use ::engine::Renderable;
                    let (rx, ry) = viewport.relative_point((self.rect.x, self.rect.y));
                    let rect = ::sdl2::rect::Rect::new_unwrap(rx, ry, self.rect.w, self.rect.h);

                    self.sprite.render(&mut context.renderer, rect);
                }

                fn data(&mut self) -> ::engine::ActorData<$actor_type> {
                    ::engine::ActorData {
                        id: self.id,
                        state: 0 as u32,
                        damage: 0,
                        resolves_collisions: false,
                        collision_filter: $filter,
                        rect: self.rect.to_sdl().unwrap(),
                        bounding_box: Some(::engine::BoundingBox::Rectangle(self.rect.clone())),
                        actor_type: $actor_type::Block,
                    }
                }

                fn change_pos(&mut self, _: &::engine::PositionChange) {}
            }
        )*
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[deriving(Clone, Copy)]
pub enum Tile {
    Empty,
    Wall,
    Floor,
}

impl Tile {

    fn walkable(&self) -> bool {
        match *self {
            Tile::Empty => false,
            Tile::Wall => false,
            Tile::Floor => true,
        }
    }

    fn repr(&self) -> char {
        match *self {
            Tile::Empty => ' ',
            Tile::Wall => '#',
            Tile::Floor => '.',
        }
    }

}

impl fmt::Show for Tile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.repr())
    }
}
<commit_msg>Make tiles functions public<commit_after>use std::fmt;

#[deriving(Clone, Copy)]
pub enum Tile {
    Empty,
    Wall,
    Floor,
}

impl Tile {

    pub fn walkable(&self) -> bool {
        match *self {
            Tile::Empty => true,
            Tile::Wall => false,
            Tile::Floor => true,
        }
    }

    pub fn repr(&self) -> char {
        match *self {
            Tile::Empty => ' ',
            Tile::Wall => '#',
            Tile::Floor => '.',
        }
    }

}

impl fmt::Show for Tile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.repr())
    }
}
<|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 euclid::{TypedPoint2D, TypedVector2D};
use glutin_app::keyutils::{CMD_OR_CONTROL, CMD_OR_ALT};
use glutin_app::window::{Window, LINE_HEIGHT};
use servo::compositing::compositor_thread::EmbedderMsg;
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
use servo::ipc_channel::ipc::IpcSender;
use servo::msg::constellation_msg::{Key, TopLevelBrowsingContextId as BrowserId};
use servo::msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
use servo::net_traits::pub_domains::is_reg_domain;
use servo::script_traits::TouchEventType;
use servo::servo_config::prefs::PREFS;
use servo::servo_url::ServoUrl;
use servo::webrender_api::ScrollLocation;
use std::mem;
use std::rc::Rc;
#[cfg(target_os = "linux")]
use std::thread;
use tinyfiledialogs;

pub struct Browser {
    current_url: Option<ServoUrl>,
    /// id of the top level browsing context. It is unique as tabs
    /// are not supported yet. None until created.
    browser_id: Option<BrowserId>,

    title: Option<String>,
    status: Option<String>,
    favicon: Option<ServoUrl>,
    loading_state: Option<LoadingState>,
    window: Rc<Window>,
    event_queue: Vec<WindowEvent>,
    shutdown_requested: bool,
}

enum LoadingState {
    Connecting,
    Loading,
    Loaded,
}

impl Browser {
    pub fn new(window: Rc<Window>) -> Browser {
        Browser {
            title: None,
            current_url: None,
            browser_id: None,
            status: None,
            favicon: None,
            loading_state: None,
            window: window,
            event_queue: Vec::new(),
            shutdown_requested: false,
        }
    }

    pub fn get_events(&mut self) -> Vec<WindowEvent> {
        mem::replace(&mut self.event_queue, Vec::new())
    }

    pub fn set_browser_id(&mut self, browser_id: BrowserId) {
        self.browser_id = Some(browser_id);
    }

    pub fn handle_window_events(&mut self, events: Vec<WindowEvent>) {
        for event in events {
            match event {
                WindowEvent::KeyEvent(ch, key, state, mods) => {
                    self.handle_key_from_window(ch, key, state, mods);
                },
                event => {
                    self.event_queue.push(event);
                }
            }
        }
    }

    pub fn shutdown_requested(&self) -> bool {
        self.shutdown_requested
    }

    /// Handle key events before sending them to Servo.
    fn handle_key_from_window(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
        match (mods, ch, key) {
            (CMD_OR_CONTROL, Some('r'), _) => {
                if let Some(id) = self.browser_id {
                    self.event_queue.push(WindowEvent::Reload(id));
                }
            }
            (CMD_OR_CONTROL, Some('l'), _) => {
                if let Some(id) = self.browser_id {
                    let url: String = if let Some(ref current_url) = self.current_url {
                        current_url.to_string()
                    } else {
                        String::from("")
                    };
                    let title = "URL or search query";
                    if let Some(input) = tinyfiledialogs::input_box(title, title, &url) {
                        if let Some(url) = sanitize_url(&input) {
                            self.event_queue.push(WindowEvent::LoadUrl(id, url));
                        }
                    }
                }
            }
            (CMD_OR_CONTROL, Some('q'), _) => {
                self.event_queue.push(WindowEvent::Quit);
            }
            (_, Some('3'), _) => if mods ^ KeyModifiers::CONTROL == KeyModifiers::SHIFT {
                self.event_queue.push(WindowEvent::CaptureWebRender);
            }
            (KeyModifiers::CONTROL, None, Key::F10) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::RenderTargetDebug);
                self.event_queue.push(event);
            }
            (KeyModifiers::CONTROL, None, Key::F11) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::TextureCacheDebug);
                self.event_queue.push(event);
            }
            (KeyModifiers::CONTROL, None, Key::F12) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::Profiler);
                self.event_queue.push(event);
            }
            (CMD_OR_ALT, None, Key::Right) | (KeyModifiers::NONE, None, Key::NavigateForward) => {
                if let Some(id) = self.browser_id {
                    let event = WindowEvent::Navigation(id, TraversalDirection::Forward(1));
                    self.event_queue.push(event);
                }
            }
            (CMD_OR_ALT, None, Key::Left) | (KeyModifiers::NONE, None, Key::NavigateBackward) => {
                if let Some(id) = self.browser_id {
                    let event = WindowEvent::Navigation(id, TraversalDirection::Back(1));
                    self.event_queue.push(event);
                }
            }
            (KeyModifiers::NONE, None, Key::Escape) => {
                self.event_queue.push(WindowEvent::Quit);
            }
            _ => {
                let event = self.platform_handle_key(key, mods);
                self.event_queue.push(event.unwrap_or(WindowEvent::KeyEvent(ch, key, state, mods)));
            }
        }

    }

    #[cfg(not(target_os = "win"))]
    fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
        match (mods, key, self.browser_id) {
            (CMD_OR_CONTROL, Key::LeftBracket, Some(id)) => {
                Some(WindowEvent::Navigation(id, TraversalDirection::Back(1)))
            }
            (CMD_OR_CONTROL, Key::RightBracket, Some(id)) => {
                Some(WindowEvent::Navigation(id, TraversalDirection::Forward(1)))
            }
            _ => None
        }
    }

    #[cfg(target_os = "win")]
    fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
        None
    }

    /// Handle key events after they have been handled by Servo.
    fn handle_key_from_servo(&mut self, _: Option<BrowserId>, ch: Option<char>,
                             key: Key, _: KeyState, mods: KeyModifiers) {
        match (mods, ch, key) {
            (_, Some('+'), _) => {
                if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL {
                    self.event_queue.push(WindowEvent::Zoom(1.1));
                } else if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL | KeyModifiers::ALT {
                    self.event_queue.push(WindowEvent::PinchZoom(1.1));
                }
            }
            (CMD_OR_CONTROL, Some('-'), _) => {
                self.event_queue.push(WindowEvent::Zoom(1.0 / 1.1));
            }
            (_, Some('-'), _) if mods == CMD_OR_CONTROL | KeyModifiers::ALT => {
                self.event_queue.push(WindowEvent::PinchZoom(1.0 / 1.1));
            }
            (CMD_OR_CONTROL, Some('0'), _) => {
                self.event_queue.push(WindowEvent::ResetZoom);
            }

            (KeyModifiers::NONE, None, Key::PageDown) => {
               let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                   -self.window.page_height() + 2.0 * LINE_HEIGHT));
                self.scroll_window_from_key(scroll_location, TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::PageUp) => {
                let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                   self.window.page_height() - 2.0 * LINE_HEIGHT));
                self.scroll_window_from_key(scroll_location, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::Home) => {
                self.scroll_window_from_key(ScrollLocation::Start, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::End) => {
                self.scroll_window_from_key(ScrollLocation::End, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::Up) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, 3.0 * LINE_HEIGHT)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Down) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, -3.0 * LINE_HEIGHT)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Left) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(LINE_HEIGHT, 0.0)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Right) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(-LINE_HEIGHT, 0.0)),
                                            TouchEventType::Move);
            }

            _ => {
            }
        }
    }

    fn scroll_window_from_key(&mut self, scroll_location: ScrollLocation, phase: TouchEventType) {
        let event = WindowEvent::Scroll(scroll_location, TypedPoint2D::zero(), phase);
        self.event_queue.push(event);
    }

    pub fn handle_servo_events(&mut self, events: Vec<EmbedderMsg>) {
        for event in events {
            match event {
                EmbedderMsg::Status(_browser_id, status) => {
                    self.status = status;
                },
                EmbedderMsg::ChangePageTitle(_browser_id, title) => {
                    self.title = title;

                    let fallback_title: String = if let Some(ref current_url) = self.current_url {
                        current_url.to_string()
                    } else {
                        String::from("Untitled")
                    };
                    let title = match self.title {
                        Some(ref title) if title.len() > 0 => &**title,
                        _ => &fallback_title,
                    };
                    let title = format!("{} - Servo", title);
                    self.window.set_title(&title);
                }
                EmbedderMsg::MoveTo(_browser_id, point) => {
                    self.window.set_position(point);
                }
                EmbedderMsg::ResizeTo(_browser_id, size) => {
                    self.window.set_inner_size(size);
                }
                EmbedderMsg::AllowNavigation(_browser_id, _url, response_chan) => {
                    if let Err(e) = response_chan.send(true) {
                        warn!("Failed to send allow_navigation() response: {}", e);
                    };
                }
                EmbedderMsg::KeyEvent(browser_id, ch, key, state, modified) => {
                    self.handle_key_from_servo(browser_id, ch, key, state, modified);
                }
                EmbedderMsg::SetCursor(cursor) => {
                    self.window.set_cursor(cursor);
                }
                EmbedderMsg::NewFavicon(_browser_id, url) => {
                    self.favicon = Some(url);
                }
                EmbedderMsg::HeadParsed(_browser_id, ) => {
                    self.loading_state = Some(LoadingState::Loading);
                }
                EmbedderMsg::HistoryChanged(_browser_id, entries, current) => {
                    self.current_url = Some(entries[current].url.clone());
                }
                EmbedderMsg::SetFullscreenState(_browser_id, state) => {
                    self.window.set_fullscreen(state);
                }
                EmbedderMsg::LoadStart(_browser_id) => {
                    self.loading_state = Some(LoadingState::Connecting);
                }
                EmbedderMsg::LoadComplete(_browser_id) => {
                    self.loading_state = Some(LoadingState::Loaded);
                }
                EmbedderMsg::Shutdown => {
                    self.shutdown_requested = true;
                },
                EmbedderMsg::Panic(_browser_id, _reason, _backtrace) => {
                },
                EmbedderMsg::GetSelectedBluetoothDevice(devices, sender) => {
                    platform_get_selected_devices(devices, sender);
                }
                EmbedderMsg::ShowIME(_browser_id, _kind) => {
                    debug!("ShowIME received");
                }
                EmbedderMsg::HideIME(_browser_id) => {
                    debug!("HideIME received");
                }
            }
        }
    }

}

#[cfg(target_os = "linux")]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
    let picker_name = "Choose a device";

    thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
        let dialog_rows: Vec<&str> = devices.iter()
            .map(|s| s.as_ref())
            .collect();
        let dialog_rows: Option<&[&str]> = Some(dialog_rows.as_slice());

        match tinyfiledialogs::list_dialog("Choose a device", &["Id", "Name"], dialog_rows) {
            Some(device) => {
                // The device string format will be "Address|Name". We need the first part of it.
                let address = device.split("|").next().map(|s| s.to_string());
                let _ = sender.send(address);
            },
            None => {
                let _ = sender.send(None);
            }
        }
    }).expect("Thread spawning failed");
}

#[cfg(not(target_os = "linux"))]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
    for device in devices {
        if let Some(address) = device.split("|").next().map(|s| s.to_string()) {
            let _ = sender.send(Some(address));
        }
    }
    let _ = sender.send(None);
}

fn sanitize_url(request: &str) -> Option<ServoUrl> {
    let request = request.trim();
    ServoUrl::parse(&request).ok()
        .or_else(|| {
            if request.contains('/') || is_reg_domain(request) {
                ServoUrl::parse(&format!("http://{}", request)).ok()
            } else {
                None
            }
        }).or_else(|| {
            PREFS.get("shell.searchpage").as_string().and_then(|s: &str| {
                let url = s.replace("%s", request);
                ServoUrl::parse(&url).ok()
            })
        })
}
<commit_msg>fix(browser): do not omit unexpected keyevent<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 euclid::{TypedPoint2D, TypedVector2D};
use glutin_app::keyutils::{CMD_OR_CONTROL, CMD_OR_ALT};
use glutin_app::window::{Window, LINE_HEIGHT};
use servo::compositing::compositor_thread::EmbedderMsg;
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
use servo::ipc_channel::ipc::IpcSender;
use servo::msg::constellation_msg::{Key, TopLevelBrowsingContextId as BrowserId};
use servo::msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
use servo::net_traits::pub_domains::is_reg_domain;
use servo::script_traits::TouchEventType;
use servo::servo_config::prefs::PREFS;
use servo::servo_url::ServoUrl;
use servo::webrender_api::ScrollLocation;
use std::mem;
use std::rc::Rc;
#[cfg(target_os = "linux")]
use std::thread;
use tinyfiledialogs;

pub struct Browser {
    current_url: Option<ServoUrl>,
    /// id of the top level browsing context. It is unique as tabs
    /// are not supported yet. None until created.
    browser_id: Option<BrowserId>,

    title: Option<String>,
    status: Option<String>,
    favicon: Option<ServoUrl>,
    loading_state: Option<LoadingState>,
    window: Rc<Window>,
    event_queue: Vec<WindowEvent>,
    shutdown_requested: bool,
}

enum LoadingState {
    Connecting,
    Loading,
    Loaded,
}

impl Browser {
    pub fn new(window: Rc<Window>) -> Browser {
        Browser {
            title: None,
            current_url: None,
            browser_id: None,
            status: None,
            favicon: None,
            loading_state: None,
            window: window,
            event_queue: Vec::new(),
            shutdown_requested: false,
        }
    }

    pub fn get_events(&mut self) -> Vec<WindowEvent> {
        mem::replace(&mut self.event_queue, Vec::new())
    }

    pub fn set_browser_id(&mut self, browser_id: BrowserId) {
        self.browser_id = Some(browser_id);
    }

    pub fn handle_window_events(&mut self, events: Vec<WindowEvent>) {
        for event in events {
            match event {
                WindowEvent::KeyEvent(ch, key, state, mods) => {
                    self.handle_key_from_window(ch, key, state, mods);
                },
                event => {
                    self.event_queue.push(event);
                }
            }
        }
    }

    pub fn shutdown_requested(&self) -> bool {
        self.shutdown_requested
    }

    /// Handle key events before sending them to Servo.
    fn handle_key_from_window(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
        match (mods, ch, key) {
            (CMD_OR_CONTROL, Some('r'), _) => {
                if let Some(id) = self.browser_id {
                    self.event_queue.push(WindowEvent::Reload(id));
                }
            }
            (CMD_OR_CONTROL, Some('l'), _) => {
                if let Some(id) = self.browser_id {
                    let url: String = if let Some(ref current_url) = self.current_url {
                        current_url.to_string()
                    } else {
                        String::from("")
                    };
                    let title = "URL or search query";
                    if let Some(input) = tinyfiledialogs::input_box(title, title, &url) {
                        if let Some(url) = sanitize_url(&input) {
                            self.event_queue.push(WindowEvent::LoadUrl(id, url));
                        }
                    }
                }
            }
            (CMD_OR_CONTROL, Some('q'), _) => {
                self.event_queue.push(WindowEvent::Quit);
            }
            (_, Some('3'), _) if mods ^ KeyModifiers::CONTROL == KeyModifiers::SHIFT => {
                self.event_queue.push(WindowEvent::CaptureWebRender);
            }
            (KeyModifiers::CONTROL, None, Key::F10) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::RenderTargetDebug);
                self.event_queue.push(event);
            }
            (KeyModifiers::CONTROL, None, Key::F11) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::TextureCacheDebug);
                self.event_queue.push(event);
            }
            (KeyModifiers::CONTROL, None, Key::F12) => {
                let event = WindowEvent::ToggleWebRenderDebug(WebRenderDebugOption::Profiler);
                self.event_queue.push(event);
            }
            (CMD_OR_ALT, None, Key::Right) | (KeyModifiers::NONE, None, Key::NavigateForward) => {
                if let Some(id) = self.browser_id {
                    let event = WindowEvent::Navigation(id, TraversalDirection::Forward(1));
                    self.event_queue.push(event);
                }
            }
            (CMD_OR_ALT, None, Key::Left) | (KeyModifiers::NONE, None, Key::NavigateBackward) => {
                if let Some(id) = self.browser_id {
                    let event = WindowEvent::Navigation(id, TraversalDirection::Back(1));
                    self.event_queue.push(event);
                }
            }
            (KeyModifiers::NONE, None, Key::Escape) => {
                self.event_queue.push(WindowEvent::Quit);
            }
            _ => {
                let event = self.platform_handle_key(key, mods);
                self.event_queue.push(event.unwrap_or(WindowEvent::KeyEvent(ch, key, state, mods)));
            }
        }

    }

    #[cfg(not(target_os = "win"))]
    fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
        match (mods, key, self.browser_id) {
            (CMD_OR_CONTROL, Key::LeftBracket, Some(id)) => {
                Some(WindowEvent::Navigation(id, TraversalDirection::Back(1)))
            }
            (CMD_OR_CONTROL, Key::RightBracket, Some(id)) => {
                Some(WindowEvent::Navigation(id, TraversalDirection::Forward(1)))
            }
            _ => None
        }
    }

    #[cfg(target_os = "win")]
    fn platform_handle_key(&self, key: Key, mods: KeyModifiers) -> Option<WindowEvent> {
        None
    }

    /// Handle key events after they have been handled by Servo.
    fn handle_key_from_servo(&mut self, _: Option<BrowserId>, ch: Option<char>,
                             key: Key, _: KeyState, mods: KeyModifiers) {
        match (mods, ch, key) {
            (_, Some('+'), _) => {
                if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL {
                    self.event_queue.push(WindowEvent::Zoom(1.1));
                } else if mods & !KeyModifiers::SHIFT == CMD_OR_CONTROL | KeyModifiers::ALT {
                    self.event_queue.push(WindowEvent::PinchZoom(1.1));
                }
            }
            (CMD_OR_CONTROL, Some('-'), _) => {
                self.event_queue.push(WindowEvent::Zoom(1.0 / 1.1));
            }
            (_, Some('-'), _) if mods == CMD_OR_CONTROL | KeyModifiers::ALT => {
                self.event_queue.push(WindowEvent::PinchZoom(1.0 / 1.1));
            }
            (CMD_OR_CONTROL, Some('0'), _) => {
                self.event_queue.push(WindowEvent::ResetZoom);
            }

            (KeyModifiers::NONE, None, Key::PageDown) => {
               let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                   -self.window.page_height() + 2.0 * LINE_HEIGHT));
                self.scroll_window_from_key(scroll_location, TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::PageUp) => {
                let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                   self.window.page_height() - 2.0 * LINE_HEIGHT));
                self.scroll_window_from_key(scroll_location, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::Home) => {
                self.scroll_window_from_key(ScrollLocation::Start, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::End) => {
                self.scroll_window_from_key(ScrollLocation::End, TouchEventType::Move);
            }

            (KeyModifiers::NONE, None, Key::Up) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, 3.0 * LINE_HEIGHT)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Down) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(0.0, -3.0 * LINE_HEIGHT)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Left) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(LINE_HEIGHT, 0.0)),
                                            TouchEventType::Move);
            }
            (KeyModifiers::NONE, None, Key::Right) => {
                self.scroll_window_from_key(ScrollLocation::Delta(TypedVector2D::new(-LINE_HEIGHT, 0.0)),
                                            TouchEventType::Move);
            }

            _ => {
            }
        }
    }

    fn scroll_window_from_key(&mut self, scroll_location: ScrollLocation, phase: TouchEventType) {
        let event = WindowEvent::Scroll(scroll_location, TypedPoint2D::zero(), phase);
        self.event_queue.push(event);
    }

    pub fn handle_servo_events(&mut self, events: Vec<EmbedderMsg>) {
        for event in events {
            match event {
                EmbedderMsg::Status(_browser_id, status) => {
                    self.status = status;
                },
                EmbedderMsg::ChangePageTitle(_browser_id, title) => {
                    self.title = title;

                    let fallback_title: String = if let Some(ref current_url) = self.current_url {
                        current_url.to_string()
                    } else {
                        String::from("Untitled")
                    };
                    let title = match self.title {
                        Some(ref title) if title.len() > 0 => &**title,
                        _ => &fallback_title,
                    };
                    let title = format!("{} - Servo", title);
                    self.window.set_title(&title);
                }
                EmbedderMsg::MoveTo(_browser_id, point) => {
                    self.window.set_position(point);
                }
                EmbedderMsg::ResizeTo(_browser_id, size) => {
                    self.window.set_inner_size(size);
                }
                EmbedderMsg::AllowNavigation(_browser_id, _url, response_chan) => {
                    if let Err(e) = response_chan.send(true) {
                        warn!("Failed to send allow_navigation() response: {}", e);
                    };
                }
                EmbedderMsg::KeyEvent(browser_id, ch, key, state, modified) => {
                    self.handle_key_from_servo(browser_id, ch, key, state, modified);
                }
                EmbedderMsg::SetCursor(cursor) => {
                    self.window.set_cursor(cursor);
                }
                EmbedderMsg::NewFavicon(_browser_id, url) => {
                    self.favicon = Some(url);
                }
                EmbedderMsg::HeadParsed(_browser_id, ) => {
                    self.loading_state = Some(LoadingState::Loading);
                }
                EmbedderMsg::HistoryChanged(_browser_id, entries, current) => {
                    self.current_url = Some(entries[current].url.clone());
                }
                EmbedderMsg::SetFullscreenState(_browser_id, state) => {
                    self.window.set_fullscreen(state);
                }
                EmbedderMsg::LoadStart(_browser_id) => {
                    self.loading_state = Some(LoadingState::Connecting);
                }
                EmbedderMsg::LoadComplete(_browser_id) => {
                    self.loading_state = Some(LoadingState::Loaded);
                }
                EmbedderMsg::Shutdown => {
                    self.shutdown_requested = true;
                },
                EmbedderMsg::Panic(_browser_id, _reason, _backtrace) => {
                },
                EmbedderMsg::GetSelectedBluetoothDevice(devices, sender) => {
                    platform_get_selected_devices(devices, sender);
                }
                EmbedderMsg::ShowIME(_browser_id, _kind) => {
                    debug!("ShowIME received");
                }
                EmbedderMsg::HideIME(_browser_id) => {
                    debug!("HideIME received");
                }
            }
        }
    }

}

#[cfg(target_os = "linux")]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
    let picker_name = "Choose a device";

    thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
        let dialog_rows: Vec<&str> = devices.iter()
            .map(|s| s.as_ref())
            .collect();
        let dialog_rows: Option<&[&str]> = Some(dialog_rows.as_slice());

        match tinyfiledialogs::list_dialog("Choose a device", &["Id", "Name"], dialog_rows) {
            Some(device) => {
                // The device string format will be "Address|Name". We need the first part of it.
                let address = device.split("|").next().map(|s| s.to_string());
                let _ = sender.send(address);
            },
            None => {
                let _ = sender.send(None);
            }
        }
    }).expect("Thread spawning failed");
}

#[cfg(not(target_os = "linux"))]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
    for device in devices {
        if let Some(address) = device.split("|").next().map(|s| s.to_string()) {
            let _ = sender.send(Some(address));
        }
    }
    let _ = sender.send(None);
}

fn sanitize_url(request: &str) -> Option<ServoUrl> {
    let request = request.trim();
    ServoUrl::parse(&request).ok()
        .or_else(|| {
            if request.contains('/') || is_reg_domain(request) {
                ServoUrl::parse(&format!("http://{}", request)).ok()
            } else {
                None
            }
        }).or_else(|| {
            PREFS.get("shell.searchpage").as_string().and_then(|s: &str| {
                let url = s.replace("%s", request);
                ServoUrl::parse(&url).ok()
            })
        })
}
<|endoftext|>


<commit_before>use gfx;
use image;
use image::{
    GenericImage,
    ImageBuf,
    Rgba,
};
use graphics::{
    ImageSize
};

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{}': {}",
                path.filename_str().unwrap(), e)),
        };

        match img.color() {
            image::RGBA(8) => {},
            c => fail!("Unsupported color type {} in png", c),
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.raw_pixels().as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &ImageBuf<Rgba<u8>>) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.pixelbuf().as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }
}

impl ImageSize for Texture {
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<commit_msg>Added Texture.update<commit_after>use gfx;
use image;
use image::{
    GenericImage,
    ImageBuf,
    Rgba,
};
use graphics::{
    ImageSize
};

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{}': {}",
                path.filename_str().unwrap(), e)),
        };

        match img.color() {
            image::RGBA(8) => {},
            c => fail!("Unsupported color type {} in png", c),
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.raw_pixels().as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &ImageBuf<Rgba<u8>>) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.pixelbuf().as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }

    /// Updates the texture with an image.
    pub fn update<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(&mut self, device: &mut D, image: &ImageBuf<Rgba<u8>>) {
        device.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            image.pixelbuf().as_slice()
        ).unwrap();
    }
}

impl ImageSize for Texture {
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flexi_logger;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use docopt::Docopt;
use flexi_logger::{detailed_format,init};
use flexi_logger::LogConfig as FlexiLogConfig;
use rustc_serialize::json;
use std::fs::File;
use std::io::Read;
use std::sync::mpsc::channel;
use std::thread;
use worker::{Request, Response, Item};
use consumer::{StompConfig, StompConsumer, Consumer};
use result_backend::{MysqlConfig, MysqlBackend, ResultBackend, ResultBackendError};
use processor::Processor;

mod consumer;
mod processor;
mod worker;
mod result_backend;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: gworkerd [options] <config>
       gworkerd (--help | --version)

Options:
    -h, --help     Print this information
    -v, --version  Show the version.
";

#[derive(RustcDecodable, Debug)]
struct Args {
  arg_config: String,
  flag_help: bool,
  flag_version: bool,
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
struct LogConfig {
  directory: String,
  levels: String
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
struct Config {
  log: LogConfig,
  threads: u32,
  stomp: StompConfig,
  mysql: MysqlConfig,
}

fn main() {
  // docopt
  let args: Args = Docopt::new(USAGE)
    .and_then(|d| d.decode())
    .unwrap_or_else(|e| e.exit());

  let mut file = File::open(args.arg_config).unwrap();
  let mut data = String::new();
  file.read_to_string(&mut data).unwrap();
  let config: Config = json::decode(&data).unwrap();

  init( FlexiLogConfig {
    log_to_file: true,
    directory: Some(config.log.directory.clone()),
    format: detailed_format,
    .. FlexiLogConfig::new()
    },
    Some(config.log.levels.clone())
  ).unwrap_or_else(|e|{panic!("Logger initialization failed with {}",e)});

  let mut threads = vec![];
  let (result_backend_tx, result_backend_rx) = channel::<Item>();

  for thread_number in 0..config.threads {
    let stomp_config = config.stomp.clone();
    let thread_tx = result_backend_tx.clone();
    let processor = thread::spawn(move || {
      // connect to message queue
      let stomp_config = stomp_config.clone();
      let mut consumer = StompConsumer::new(&stomp_config);
      {
        let subscription_tx = thread_tx.clone();
        consumer.subscribe(move |request: Request| {
          info!("[{:?}] executing {} in cwd {}", request.id, request.program, request.cwd);

          let response : Response = Processor::run(request.clone());

          info!("[{:?}] finished with status: {:?}", request.id, response.status);
          debug!("[{:?}] finished with stdout: {:?}", request.id, response.stdout);
          debug!("[{:?}] finished with stderr: {:?}", request.id, response.stderr);

          let item = worker::Item { request: request.clone(), response: response };
          subscription_tx.send(item.clone()).unwrap();
        });
      }
      info!("start listening for thread {:?}", thread_number);
      consumer.listen();
    });
    threads.push(processor);
  }

  let connection = MysqlBackend::new(config.mysql.new_pool());
  let result_backend = thread::spawn(move || {
    let connection = connection.clone();
    loop {
      let item = result_backend_rx.recv().unwrap();
      match connection.store(&item) {
        Err(ResultBackendError::CannotStoreResult) => {
          error!("[{:?}] cannot add to result backend", item.request.id);
        },
        Ok(_) => {
          info!("[{:?}] added to result backend", item.request.id);
        }
      }

    }
  });

  for item in threads {
    item.join().ok().expect("unable to join processor thread");
  }

  result_backend.join().ok().expect("unable to join result backend thread");
}<commit_msg>better naming<commit_after>extern crate docopt;
extern crate flexi_logger;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use docopt::Docopt;
use flexi_logger::{detailed_format,init};
use flexi_logger::LogConfig as FlexiLogConfig;
use rustc_serialize::json;
use std::fs::File;
use std::io::Read;
use std::sync::mpsc::channel;
use std::thread;
use worker::{Request, Response, Item};
use consumer::{StompConfig, StompConsumer, Consumer};
use result_backend::{MysqlConfig, MysqlBackend, ResultBackend, ResultBackendError};
use processor::Processor;

mod consumer;
mod processor;
mod worker;
mod result_backend;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: gworkerd [options] <config>
       gworkerd (--help | --version)

Options:
    -h, --help     Print this information
    -v, --version  Show the version.
";

#[derive(RustcDecodable, Debug)]
struct Args {
  arg_config: String,
  flag_help: bool,
  flag_version: bool,
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
struct LogConfig {
  directory: String,
  levels: String
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
struct Config {
  log: LogConfig,
  threads: u32,
  stomp: StompConfig,
  mysql: MysqlConfig,
}

fn main() {
  // docopt
  let args: Args = Docopt::new(USAGE)
    .and_then(|d| d.decode())
    .unwrap_or_else(|e| e.exit());

  let mut file = File::open(args.arg_config).unwrap();
  let mut data = String::new();
  file.read_to_string(&mut data).unwrap();
  let config: Config = json::decode(&data).unwrap();

  init( FlexiLogConfig {
    log_to_file: true,
    directory: Some(config.log.directory.clone()),
    format: detailed_format,
    .. FlexiLogConfig::new()
    },
    Some(config.log.levels.clone())
  ).unwrap_or_else(|e|{panic!("Logger initialization failed with {}",e)});

  let mut threads = vec![];
  let (result_backend_tx, result_backend_rx) = channel::<Item>();

  for thread_number in 0..config.threads {
    let stomp_config = config.stomp.clone();
    let thread_tx = result_backend_tx.clone();
    let processor = thread::spawn(move || {
      // connect to message queue
      let stomp_config = stomp_config.clone();
      let mut consumer = StompConsumer::new(&stomp_config);
      {
        let subscription_tx = thread_tx.clone();
        consumer.subscribe(move |request: Request| {
          info!("[{:?}] executing {} in cwd {}", request.id, request.program, request.cwd);

          let response : Response = Processor::run(request.clone());

          info!("[{:?}] finished with status: {:?}", request.id, response.status);
          debug!("[{:?}] finished with stdout: {:?}", request.id, response.stdout);
          debug!("[{:?}] finished with stderr: {:?}", request.id, response.stderr);

          let item = worker::Item { request: request.clone(), response: response };
          subscription_tx.send(item.clone()).unwrap();
        });
      }
      info!("start listening for thread {:?}", thread_number);
      consumer.listen();
    });
    threads.push(processor);
  }

  let result_connection = MysqlBackend::new(config.mysql.new_pool());
  let result_thread = thread::spawn(move || {
    let connection = result_connection.clone();
    loop {
      let item = result_backend_rx.recv().unwrap();
      match connection.store(&item) {
        Err(ResultBackendError::CannotStoreResult) => {
          error!("[{:?}] cannot add to result backend", item.request.id);
        },
        Ok(_) => {
          info!("[{:?}] added to result backend", item.request.id);
        }
      }

    }
  });

  for item in threads {
    item.join().ok().expect("unable to join processor thread");
  }

  result_thread.join().ok().expect("unable to join result backend thread");
}<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate petgraph;

use std::rand::{Rng, thread_rng, ChaChaRng};
use std::collections::HashSet;
use petgraph::unionfind::UnionFind;

#[test]
fn uf_test() {
    let n = 8;
    let mut u = UnionFind::new(n);
    for i in range(0, n) {
        assert_eq!(u.find(i), i);
        assert_eq!(u.find_mut(i), i);
        assert!(!u.union(i, i));
    }

    u.union(0, 1);
    assert_eq!(u.find(0), u.find(1));
    u.union(1, 3);
    u.union(1, 4);
    u.union(4, 7);
    assert_eq!(u.find(0), u.find(3));
    assert_eq!(u.find(1), u.find(3));
    assert!(u.find(0) != u.find(2));
    assert_eq!(u.find(7), u.find(0));
    u.union(5, 6);
    assert_eq!(u.find(6), u.find(5));
    assert!(u.find(6) != u.find(7));

    // check that there are now 3 disjoint sets
    let set = range(0, n).map(|i| u.find(i)).collect::<HashSet<_>>();
    assert_eq!(set.len(), 3);
}

#[test]
fn uf_rand() {
    let n = 1 << 14;
    let mut rng: ChaChaRng = thread_rng().gen();
    let mut u = UnionFind::new(n);
    for i in range(0, n * 8) {
        let a = rng.gen_range(0, n);
        let b = rng.gen_range(0, n);
        let ar = u.find(a);
        let br = u.find(b);
        assert_eq!(ar != br, u.union(a, b));
        if (i + 1) % n == 0 {
            let set = range(0, n).map(|i| u.find(i)).collect::<HashSet<_>>();
            println!("Disjoint parts={:?}", set.len());
            //println!("Disjoint parts={:?} maxrank={:?}", set.len(), u.rank.iter().max_by(|t| *t));
        }
    }
}

#[test]
fn uf_u8() {
    let n = 256;
    let mut rng: ChaChaRng = thread_rng().gen();
    let mut u = UnionFind::<u8>::new(n);
    for i in range(0, n * 8) {
        let a = rng.gen();
        let b = rng.gen();
        let ar = u.find(a);
        let br = u.find(b);
        assert_eq!(ar != br, u.union(a, b));
    }
}

#[test]
fn labeling()
{
    let mut u = UnionFind::new(48);
    for i in (0..24u32) {
        u.union(i + 1, i);
    }
    for i in (25..47) {
        u.union(i, i + 1);
    }
    u.union(23, 25);
    u.union(24, 23);
    let v = u.into_labeling();
    assert!(v.iter().all(|x| *x == v[0]));
}
<commit_msg>Update for range change<commit_after>#![allow(unstable)]

extern crate petgraph;

use std::rand::{Rng, thread_rng, ChaChaRng};
use std::collections::HashSet;
use petgraph::unionfind::UnionFind;

#[test]
fn uf_test() {
    let n = 8;
    let mut u = UnionFind::new(n);
    for i in range(0, n) {
        assert_eq!(u.find(i), i);
        assert_eq!(u.find_mut(i), i);
        assert!(!u.union(i, i));
    }

    u.union(0, 1);
    assert_eq!(u.find(0), u.find(1));
    u.union(1, 3);
    u.union(1, 4);
    u.union(4, 7);
    assert_eq!(u.find(0), u.find(3));
    assert_eq!(u.find(1), u.find(3));
    assert!(u.find(0) != u.find(2));
    assert_eq!(u.find(7), u.find(0));
    u.union(5, 6);
    assert_eq!(u.find(6), u.find(5));
    assert!(u.find(6) != u.find(7));

    // check that there are now 3 disjoint sets
    let set = range(0, n).map(|i| u.find(i)).collect::<HashSet<_>>();
    assert_eq!(set.len(), 3);
}

#[test]
fn uf_rand() {
    let n = 1 << 14;
    let mut rng: ChaChaRng = thread_rng().gen();
    let mut u = UnionFind::new(n);
    for i in range(0, n * 8) {
        let a = rng.gen_range(0, n);
        let b = rng.gen_range(0, n);
        let ar = u.find(a);
        let br = u.find(b);
        assert_eq!(ar != br, u.union(a, b));
        if (i + 1) % n == 0 {
            let set = range(0, n).map(|i| u.find(i)).collect::<HashSet<_>>();
            println!("Disjoint parts={:?}", set.len());
            //println!("Disjoint parts={:?} maxrank={:?}", set.len(), u.rank.iter().max_by(|t| *t));
        }
    }
}

#[test]
fn uf_u8() {
    let n = 256;
    let mut rng: ChaChaRng = thread_rng().gen();
    let mut u = UnionFind::<u8>::new(n);
    for i in range(0, n * 8) {
        let a = rng.gen();
        let b = rng.gen();
        let ar = u.find(a);
        let br = u.find(b);
        assert_eq!(ar != br, u.union(a, b));
    }
}

#[test]
fn labeling()
{
    let mut u = UnionFind::new(48);
    for i in (0..24u32) {
        u.union(i + 1, i);
    }
    for i in (25u32..47) {
        u.union(i, i + 1);
    }
    u.union(23, 25);
    u.union(24, 23);
    let v = u.into_labeling();
    assert!(v.iter().all(|x| *x == v[0]));
}
<|endoftext|>


<commit_before>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use subscription::AckMode;
use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::InvalidInput;
use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::str::from_utf8;
use std::fmt;
use std::fmt::Formatter;
use frame::{Frame, Transmission};

pub struct FrameBuffer {
  buffer: Vec<u8>,
  parse_state: ParseState
}

#[derive(Clone, Copy)]
struct ByteRange {
  pub start: u32,
  pub end : u32
}

struct ParseState {
  offset: u32,
  command_range: Option<ByteRange>,
  header_ranges: Vec<ByteRange>,
  body_range: Option<ByteRange>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      offset: 0,
      command_range: None,
      header_ranges: Vec::new(),
      body_range: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(ByteRange),
  Incomplete
}

enum ReadHeaderResult {
  Header(ByteRange),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(ByteRange),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer {
      buffer: Vec::with_capacity(512),
      parse_state: ParseState::new()
    }
  }

  pub fn append(&mut self, bytes: &[u8]) { // TODO: Return result?
    self.buffer.push_all(bytes);
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(byte_range) => {
        self.parse_state.command_range = Some(byte_range);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(byte_range) => {
        self.parse_state.header_ranges.push(byte_range);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(byte_range) => {
        self.parse_state.body_range = Some(byte_range);
        let frame = Frame {
          command: self.create_command_string(),
          headers: self.create_header_list(),
          body: self.create_body()
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.buffer.clear();
    self.parse_state.offset = 0;
    self.parse_state.command_range = None;
    self.parse_state.header_ranges.clear();
    self.parse_state.body_range = None;
    self.parse_state.section = FrameSection::Command;
  }

  fn create_command_string(&mut self) -> String {
    let buffer : &[u8] = self.buffer.as_ref();
    let command_range = self.parse_state.command_range.expect("No command range was found.");
    let start = command_range.start;
    let end = command_range.end;
    let command_slice = &buffer[start as usize..end as usize];
    let command_str : &str = match from_utf8(&command_slice) {
      Ok(command_str) => command_str,
      _ =>panic!("Command was not utf8.")
    };
    return command_str.to_string();
  }

  fn create_header_list(&mut self) -> HeaderList {
    let buffer : &[u8] = self.buffer.as_ref();
    let mut header_list = header_list![];
    for header_range in &self.parse_state.header_ranges {
      let start = header_range.start;
      let end = header_range.end;
      let header_slice = &buffer[start as usize..end as usize];
      let header_str : &str = match from_utf8(&header_slice) {
        Ok(header_str) => header_str,
        _ =>panic!("Header was not utf8.")
      };
      let header = Header::decode_string(header_str);
      match header {
        Some(header) => header_list.push(header),
        None => panic!("Header was not decodable.")
      }
    }
    header_list
  }

  fn create_body(&mut self) -> Vec<u8> {
    let buffer : &[u8] = self.buffer.as_ref();
    let body_range = self.parse_state.body_range.expect("No body range was found.");
    let start = body_range.start;
    let end = body_range.end;
    let body_slice = &buffer[start as usize ..end as usize];
    return Vec::from(body_slice);
  }

  fn read_command(&self) -> ReadCommandResult {
    let offset = self.parse_state.offset;
    match self.find_next(offset, '\n' as u8) {
      Some(index) => {
        self.parse_state.offset += index - offset;
        if index == offset {
          ReadCommandResult::HeartBeat(ByteRange{start: offset, end: index})
        } else {
          ReadCommandResult::Command(ByteRange{start: offset, end: index})
        }
      }
      None => ReadCommandResult::Incomplete
    }
  }

  fn read_header(&self) -> ReadHeaderResult {
    let offset = self.parse_state.offset;
    match self.find_next(offset, '\n' as u8) {
      Some(index) => {
        self.parse_state.offset += index - offset;
        ReadHeaderResult::Header(ByteRange{start: offset, end: index})
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // Need to read both by Content-Length and by null byte
  fn read_body(&self) -> ReadBodyResult {
    ReadBodyResult::Incomplete
  }

  fn find_next(&self, offset: u32, needle: u8) -> Option<u32> {
    // What's the len() of the underlying slice? capacity or size?
    let mut step = 0u32;
    for byte in &self.buffer[offset as usize..] {
      if *byte == needle {
        return Some(offset + step);
      }
      step += 1;
    }
    None
  }
}
<commit_msg>Some todos.<commit_after>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use subscription::AckMode;
use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::InvalidInput;
use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::str::from_utf8;
use std::fmt;
use std::fmt::Formatter;
use frame::{Frame, Transmission};

pub struct FrameBuffer {
  buffer: Vec<u8>,
  parse_state: ParseState
}

#[derive(Clone, Copy)]
struct ByteRange {
  pub start: u32,
  pub end : u32
}

struct ParseState {
  offset: u32,
  command_range: Option<ByteRange>,
  header_ranges: Vec<ByteRange>,
  body_range: Option<ByteRange>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      offset: 0,
      command_range: None,
      header_ranges: Vec::new(),
      body_range: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(ByteRange),
  Incomplete
}

enum ReadHeaderResult {
  Header(ByteRange),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(ByteRange),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer {
      buffer: Vec::with_capacity(512), //TODO: VecDeque?
      parse_state: ParseState::new()
    }
  }

  pub fn append(&mut self, bytes: &[u8]) { // TODO: Return result?
    self.buffer.push_all(bytes);
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(byte_range) => {
        self.parse_state.command_range = Some(byte_range);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(byte_range) => {
        self.parse_state.header_ranges.push(byte_range);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(byte_range) => {
        self.parse_state.body_range = Some(byte_range);
        let frame = Frame {
          command: self.create_command_string(),
          headers: self.create_header_list(),
          body: self.create_body()
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.buffer.clear(); // TODO: Not clear, shift/shrink
    self.parse_state.offset = 0;
    self.parse_state.command_range = None;
    self.parse_state.header_ranges.clear();
    self.parse_state.body_range = None;
    self.parse_state.section = FrameSection::Command;
  }

  fn create_command_string(&mut self) -> String {
    let buffer : &[u8] = self.buffer.as_ref();
    let command_range = self.parse_state.command_range.expect("No command range was found.");
    let start = command_range.start;
    let end = command_range.end;
    let command_slice = &buffer[start as usize..end as usize];
    let command_str : &str = match from_utf8(&command_slice) {
      Ok(command_str) => command_str,
      _ =>panic!("Command was not utf8.")
    };
    return command_str.to_string();
  }

  fn create_header_list(&mut self) -> HeaderList {
    let buffer : &[u8] = self.buffer.as_ref();
    let mut header_list = header_list![];
    for header_range in &self.parse_state.header_ranges {
      let start = header_range.start;
      let end = header_range.end;
      let header_slice = &buffer[start as usize..end as usize];
      let header_str : &str = match from_utf8(&header_slice) {
        Ok(header_str) => header_str,
        _ =>panic!("Header was not utf8.")
      };
      let header = Header::decode_string(header_str);
      match header {
        Some(header) => header_list.push(header),
        None => panic!("Header was not decodable.")
      }
    }
    header_list
  }

  fn create_body(&mut self) -> Vec<u8> {
    let buffer : &[u8] = self.buffer.as_ref();
    let body_range = self.parse_state.body_range.expect("No body range was found.");
    let start = body_range.start;
    let end = body_range.end;
    let body_slice = &buffer[start as usize ..end as usize];
    return Vec::from(body_slice);
  }

  fn read_command(&self) -> ReadCommandResult {
    let offset = self.parse_state.offset;
    match self.find_next(offset, '\n' as u8) {
      Some(index) => {
        self.parse_state.offset += index - offset;
        if index == offset {
          ReadCommandResult::HeartBeat(ByteRange{start: offset, end: index})
        } else {
          ReadCommandResult::Command(ByteRange{start: offset, end: index})
        }
      }
      None => ReadCommandResult::Incomplete
    }
  }

  fn read_header(&self) -> ReadHeaderResult {
    let offset = self.parse_state.offset;
    match self.find_next(offset, '\n' as u8) {
      Some(index) => {
        self.parse_state.offset += index - offset;
        ReadHeaderResult::Header(ByteRange{start: offset, end: index})
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // TODO: Need to read both by Content-Length and by null byte
  fn read_body(&self) -> ReadBodyResult {
    ReadBodyResult::Incomplete
  }

  fn find_next(&self, offset: u32, needle: u8) -> Option<u32> {
    // TODO: What's the len() of the underlying slice? capacity or size?
    let mut step = 0u32;
    for byte in &self.buffer[offset as usize..] {
      if *byte == needle {
        return Some(offset + step);
      }
      step += 1;
    }
    None
  }
}
<|endoftext|>