<commit_before>//! FIXME: write short doc here
mod lower;

use std::{ops::Index, sync::Arc};

use hir_expand::{either::Either, HirFileId, MacroDefId, Source};
use ra_arena::{map::ArenaMap, Arena};
use ra_syntax::{ast, AstPtr};
use rustc_hash::FxHashMap;

use crate::{
    db::DefDatabase2,
    expr::{Expr, ExprId, Pat, PatId},
    nameres::CrateDefMap,
    path::Path,
    ModuleId,
};

pub struct MacroResolver {
    crate_def_map: Arc<CrateDefMap>,
    module: ModuleId,
}

impl MacroResolver {
    pub fn new(db: &impl DefDatabase2, module: ModuleId) -> MacroResolver {
        MacroResolver { crate_def_map: db.crate_def_map(module.krate), module }
    }

    pub(crate) fn resolve_path_as_macro(
        &self,
        db: &impl DefDatabase2,
        path: &Path,
    ) -> Option<MacroDefId> {
        self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros()
    }
}

/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
    exprs: Arena<ExprId, Expr>,
    pats: Arena<PatId, Pat>,
    /// The patterns for the function's parameters. While the parameter types are
    /// part of the function signature, the patterns are not (they don't change
    /// the external type of the function).
    ///
    /// If this `Body` is for the body of a constant, this will just be
    /// empty.
    params: Vec<PatId>,
    /// The `ExprId` of the actual body expression.
    body_expr: ExprId,
}

pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
pub type ExprSource = Source<ExprPtr>;

pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
pub type PatSource = Source<PatPtr>;

/// An item body together with the mapping from syntax nodes to HIR expression
/// IDs. This is needed to go from e.g. a position in a file to the HIR
/// expression containing it; but for type inference etc., we want to operate on
/// a structure that is agnostic to the actual positions of expressions in the
/// file, so that we don't recompute types whenever some whitespace is typed.
///
/// One complication here is that, due to macro expansion, a single `Body` might
/// be spread across several files. So, for each ExprId and PatId, we record
/// both the HirFileId and the position inside the file. However, we only store
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
/// this properly for macros.
#[derive(Default, Debug, Eq, PartialEq)]
pub struct BodySourceMap {
    expr_map: FxHashMap<ExprPtr, ExprId>,
    expr_map_back: ArenaMap<ExprId, ExprSource>,
    pat_map: FxHashMap<PatPtr, PatId>,
    pat_map_back: ArenaMap<PatId, PatSource>,
    field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
}

impl Body {
    pub fn new(
        db: &impl DefDatabase2,
        resolver: MacroResolver,
        file_id: HirFileId,
        params: Option<ast::ParamList>,
        body: Option<ast::Expr>,
    ) -> (Body, BodySourceMap) {
        lower::lower(db, resolver, file_id, params, body)
    }

    pub fn params(&self) -> &[PatId] {
        &self.params
    }

    pub fn body_expr(&self) -> ExprId {
        self.body_expr
    }

    pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
        self.exprs.iter()
    }

    pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
        self.pats.iter()
    }
}

impl Index<ExprId> for Body {
    type Output = Expr;

    fn index(&self, expr: ExprId) -> &Expr {
        &self.exprs[expr]
    }
}

impl Index<PatId> for Body {
    type Output = Pat;

    fn index(&self, pat: PatId) -> &Pat {
        &self.pats[pat]
    }
}

impl BodySourceMap {
    pub fn expr_syntax(&self, expr: ExprId) -> Option<ExprSource> {
        self.expr_map_back.get(expr).copied()
    }

    pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
        self.expr_map.get(&Either::A(AstPtr::new(node))).cloned()
    }

    pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
        self.pat_map_back.get(pat).copied()
    }

    pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
        self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
    }

    pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
        self.field_map[&(expr, field)]
    }
}
<commit_msg>Reduce visibility<commit_after>//! FIXME: write short doc here
mod lower;

use std::{ops::Index, sync::Arc};

use hir_expand::{either::Either, HirFileId, MacroDefId, Source};
use ra_arena::{map::ArenaMap, Arena};
use ra_syntax::{ast, AstPtr};
use rustc_hash::FxHashMap;

use crate::{
    db::DefDatabase2,
    expr::{Expr, ExprId, Pat, PatId},
    nameres::CrateDefMap,
    path::Path,
    ModuleId,
};

pub struct MacroResolver {
    crate_def_map: Arc<CrateDefMap>,
    module: ModuleId,
}

impl MacroResolver {
    pub fn new(db: &impl DefDatabase2, module: ModuleId) -> MacroResolver {
        MacroResolver { crate_def_map: db.crate_def_map(module.krate), module }
    }

    fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> {
        self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros()
    }
}

/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
    exprs: Arena<ExprId, Expr>,
    pats: Arena<PatId, Pat>,
    /// The patterns for the function's parameters. While the parameter types are
    /// part of the function signature, the patterns are not (they don't change
    /// the external type of the function).
    ///
    /// If this `Body` is for the body of a constant, this will just be
    /// empty.
    params: Vec<PatId>,
    /// The `ExprId` of the actual body expression.
    body_expr: ExprId,
}

pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
pub type ExprSource = Source<ExprPtr>;

pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
pub type PatSource = Source<PatPtr>;

/// An item body together with the mapping from syntax nodes to HIR expression
/// IDs. This is needed to go from e.g. a position in a file to the HIR
/// expression containing it; but for type inference etc., we want to operate on
/// a structure that is agnostic to the actual positions of expressions in the
/// file, so that we don't recompute types whenever some whitespace is typed.
///
/// One complication here is that, due to macro expansion, a single `Body` might
/// be spread across several files. So, for each ExprId and PatId, we record
/// both the HirFileId and the position inside the file. However, we only store
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
/// this properly for macros.
#[derive(Default, Debug, Eq, PartialEq)]
pub struct BodySourceMap {
    expr_map: FxHashMap<ExprPtr, ExprId>,
    expr_map_back: ArenaMap<ExprId, ExprSource>,
    pat_map: FxHashMap<PatPtr, PatId>,
    pat_map_back: ArenaMap<PatId, PatSource>,
    field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
}

impl Body {
    pub fn new(
        db: &impl DefDatabase2,
        resolver: MacroResolver,
        file_id: HirFileId,
        params: Option<ast::ParamList>,
        body: Option<ast::Expr>,
    ) -> (Body, BodySourceMap) {
        lower::lower(db, resolver, file_id, params, body)
    }

    pub fn params(&self) -> &[PatId] {
        &self.params
    }

    pub fn body_expr(&self) -> ExprId {
        self.body_expr
    }

    pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
        self.exprs.iter()
    }

    pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
        self.pats.iter()
    }
}

impl Index<ExprId> for Body {
    type Output = Expr;

    fn index(&self, expr: ExprId) -> &Expr {
        &self.exprs[expr]
    }
}

impl Index<PatId> for Body {
    type Output = Pat;

    fn index(&self, pat: PatId) -> &Pat {
        &self.pats[pat]
    }
}

impl BodySourceMap {
    pub fn expr_syntax(&self, expr: ExprId) -> Option<ExprSource> {
        self.expr_map_back.get(expr).copied()
    }

    pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
        self.expr_map.get(&Either::A(AstPtr::new(node))).cloned()
    }

    pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
        self.pat_map_back.get(pat).copied()
    }

    pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
        self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
    }

    pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
        self.field_map[&(expr, field)]
    }
}
<|endoftext|>


<commit_before>//! Defines the most basic types and constants like the pieces,
//! colors, squares, files, and ranks.
//!
//! This module also defines few simple functions.

/// `WHITE` or `BLACK`.
pub type Color = usize; // 0 or 1

/// `KING`, `QUEEN`, `ROOK`, `BISHOP`, `KINGHT`, `PAWN`, `NO_PIECE`,
/// or `UNKNOWN_PIECE`.
pub type PieceType = usize;  // from 0 to 5

/// From 0 to 7 (0 is rank 1, 7 is rank 8).
pub type Rank = usize;  // from 0 to 7

/// From 0 to 7 (0 is file A, 7 is file H).
pub type File = usize;  // from 0 to 7

/// From 0 to 63 (0 is A1, 63 is H8).
pub type Square = usize;  // from 0 to 63

/// Number of searched positions.
pub type NodeCount = u64;

/// Evaluation value in centipawns.
///
/// Positive values mean that the position is favorable for the side
/// to move. Negative values mean the position is favorable for the
/// other side (not to move). A value of `0` means that the chances
/// are equal. For example: a value of `100` might mean that the side
/// to move is a pawn ahead.
///
/// Values over `19999` and under `-19999` designate a certain
/// win/loss.
pub type Value = i16;

// Color
pub const WHITE: Color = 0;
pub const BLACK: Color = 1;

// Piece types
pub const KING: PieceType = 0;
pub const QUEEN: PieceType = 1;
pub const ROOK: PieceType = 2;
pub const BISHOP: PieceType = 3;
pub const KNIGHT: PieceType = 4;
pub const PAWN: PieceType = 5;
pub const NO_PIECE: PieceType = 6;
pub const UNKNOWN_PIECE: PieceType = 7;

// Ranks
pub const RANK_1: Rank = 0;
pub const RANK_2: Rank = 1;
pub const RANK_3: Rank = 2;
pub const RANK_4: Rank = 3;
pub const RANK_5: Rank = 4;
pub const RANK_6: Rank = 5;
pub const RANK_7: Rank = 6;
pub const RANK_8: Rank = 7;

// Files
pub const FILE_A: Rank = 0;
pub const FILE_B: Rank = 1;
pub const FILE_C: Rank = 2;
pub const FILE_D: Rank = 3;
pub const FILE_E: Rank = 4;
pub const FILE_F: Rank = 5;
pub const FILE_G: Rank = 6;
pub const FILE_H: Rank = 7;

// Squares
pub const A1: Square = 0 + 0 * 8;
pub const B1: Square = 1 + 0 * 8;
pub const C1: Square = 2 + 0 * 8;
pub const D1: Square = 3 + 0 * 8;
pub const E1: Square = 4 + 0 * 8;
pub const F1: Square = 5 + 0 * 8;
pub const G1: Square = 6 + 0 * 8;
pub const H1: Square = 7 + 0 * 8;
pub const A2: Square = 0 + 1 * 8;
pub const B2: Square = 1 + 1 * 8;
pub const C2: Square = 2 + 1 * 8;
pub const D2: Square = 3 + 1 * 8;
pub const E2: Square = 4 + 1 * 8;
pub const F2: Square = 5 + 1 * 8;
pub const G2: Square = 6 + 1 * 8;
pub const H2: Square = 7 + 1 * 8;
pub const A3: Square = 0 + 2 * 8;
pub const B3: Square = 1 + 2 * 8;
pub const C3: Square = 2 + 2 * 8;
pub const D3: Square = 3 + 2 * 8;
pub const E3: Square = 4 + 2 * 8;
pub const F3: Square = 5 + 2 * 8;
pub const G3: Square = 6 + 2 * 8;
pub const H3: Square = 7 + 2 * 8;
pub const A4: Square = 0 + 3 * 8;
pub const B4: Square = 1 + 3 * 8;
pub const C4: Square = 2 + 3 * 8;
pub const D4: Square = 3 + 3 * 8;
pub const E4: Square = 4 + 3 * 8;
pub const F4: Square = 5 + 3 * 8;
pub const G4: Square = 6 + 3 * 8;
pub const H4: Square = 7 + 3 * 8;
pub const A5: Square = 0 + 4 * 8;
pub const B5: Square = 1 + 4 * 8;
pub const C5: Square = 2 + 4 * 8;
pub const D5: Square = 3 + 4 * 8;
pub const E5: Square = 4 + 4 * 8;
pub const F5: Square = 5 + 4 * 8;
pub const G5: Square = 6 + 4 * 8;
pub const H5: Square = 7 + 4 * 8;
pub const A6: Square = 0 + 5 * 8;
pub const B6: Square = 1 + 5 * 8;
pub const C6: Square = 2 + 5 * 8;
pub const D6: Square = 3 + 5 * 8;
pub const E6: Square = 4 + 5 * 8;
pub const F6: Square = 5 + 5 * 8;
pub const G6: Square = 6 + 5 * 8;
pub const H6: Square = 7 + 5 * 8;
pub const A7: Square = 0 + 6 * 8;
pub const B7: Square = 1 + 6 * 8;
pub const C7: Square = 2 + 6 * 8;
pub const D7: Square = 3 + 6 * 8;
pub const E7: Square = 4 + 6 * 8;
pub const F7: Square = 5 + 6 * 8;
pub const G7: Square = 6 + 6 * 8;
pub const H7: Square = 7 + 6 * 8;
pub const A8: Square = 0 + 7 * 8;
pub const B8: Square = 1 + 7 * 8;
pub const C8: Square = 2 + 7 * 8;
pub const D8: Square = 3 + 7 * 8;
pub const E8: Square = 4 + 7 * 8;
pub const F8: Square = 5 + 7 * 8;
pub const G8: Square = 6 + 7 * 8;
pub const H8: Square = 7 + 7 * 8;

/// Returns the square on given file and rank.
#[inline]
pub fn square(file: File, rank: Rank) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

/// Returns the rank of a given square.
#[inline(always)]
pub fn rank(square: Square) -> Rank {
    square >> 3
}

/// Returns the file of a given square.
#[inline(always)]
pub fn file(square: Square) -> File {
    square % 8
}

/// Returns the algebraic notation for a given square.
pub fn notation(square: Square) -> &'static str {
    lazy_static! {
        static ref NOTATION: Vec<String> = (0..64).map(|i| format!("{}{}",
            ["a", "b", "c", "d", "e", "f", "g", "h"][file(i)],
            ["1", "2", "3", "4", "5", "6", "7", "8"][rank(i)])
        ).collect();
    }
    NOTATION[square].as_str()
}
<commit_msg>added asserts<commit_after>//! Defines the most basic types and constants like the pieces,
//! colors, squares, files, and ranks.
//!
//! This module also defines few simple functions.

/// `WHITE` or `BLACK`.
pub type Color = usize; // 0 or 1

/// `KING`, `QUEEN`, `ROOK`, `BISHOP`, `KINGHT`, `PAWN`, `NO_PIECE`,
/// or `UNKNOWN_PIECE`.
pub type PieceType = usize;  // from 0 to 5

/// From 0 to 7 (0 is rank 1, 7 is rank 8).
pub type Rank = usize;  // from 0 to 7

/// From 0 to 7 (0 is file A, 7 is file H).
pub type File = usize;  // from 0 to 7

/// From 0 to 63 (0 is A1, 63 is H8).
pub type Square = usize;  // from 0 to 63

/// Number of searched positions.
pub type NodeCount = u64;

/// Evaluation value in centipawns.
///
/// Positive values mean that the position is favorable for the side
/// to move. Negative values mean the position is favorable for the
/// other side (not to move). A value of `0` means that the chances
/// are equal. For example: a value of `100` might mean that the side
/// to move is a pawn ahead.
///
/// Values over `19999` and under `-19999` designate a certain
/// win/loss.
pub type Value = i16;

// Color
pub const WHITE: Color = 0;
pub const BLACK: Color = 1;

// Piece types
pub const KING: PieceType = 0;
pub const QUEEN: PieceType = 1;
pub const ROOK: PieceType = 2;
pub const BISHOP: PieceType = 3;
pub const KNIGHT: PieceType = 4;
pub const PAWN: PieceType = 5;
pub const NO_PIECE: PieceType = 6;
pub const UNKNOWN_PIECE: PieceType = 7;

// Ranks
pub const RANK_1: Rank = 0;
pub const RANK_2: Rank = 1;
pub const RANK_3: Rank = 2;
pub const RANK_4: Rank = 3;
pub const RANK_5: Rank = 4;
pub const RANK_6: Rank = 5;
pub const RANK_7: Rank = 6;
pub const RANK_8: Rank = 7;

// Files
pub const FILE_A: Rank = 0;
pub const FILE_B: Rank = 1;
pub const FILE_C: Rank = 2;
pub const FILE_D: Rank = 3;
pub const FILE_E: Rank = 4;
pub const FILE_F: Rank = 5;
pub const FILE_G: Rank = 6;
pub const FILE_H: Rank = 7;

// Squares
pub const A1: Square = 0 + 0 * 8;
pub const B1: Square = 1 + 0 * 8;
pub const C1: Square = 2 + 0 * 8;
pub const D1: Square = 3 + 0 * 8;
pub const E1: Square = 4 + 0 * 8;
pub const F1: Square = 5 + 0 * 8;
pub const G1: Square = 6 + 0 * 8;
pub const H1: Square = 7 + 0 * 8;
pub const A2: Square = 0 + 1 * 8;
pub const B2: Square = 1 + 1 * 8;
pub const C2: Square = 2 + 1 * 8;
pub const D2: Square = 3 + 1 * 8;
pub const E2: Square = 4 + 1 * 8;
pub const F2: Square = 5 + 1 * 8;
pub const G2: Square = 6 + 1 * 8;
pub const H2: Square = 7 + 1 * 8;
pub const A3: Square = 0 + 2 * 8;
pub const B3: Square = 1 + 2 * 8;
pub const C3: Square = 2 + 2 * 8;
pub const D3: Square = 3 + 2 * 8;
pub const E3: Square = 4 + 2 * 8;
pub const F3: Square = 5 + 2 * 8;
pub const G3: Square = 6 + 2 * 8;
pub const H3: Square = 7 + 2 * 8;
pub const A4: Square = 0 + 3 * 8;
pub const B4: Square = 1 + 3 * 8;
pub const C4: Square = 2 + 3 * 8;
pub const D4: Square = 3 + 3 * 8;
pub const E4: Square = 4 + 3 * 8;
pub const F4: Square = 5 + 3 * 8;
pub const G4: Square = 6 + 3 * 8;
pub const H4: Square = 7 + 3 * 8;
pub const A5: Square = 0 + 4 * 8;
pub const B5: Square = 1 + 4 * 8;
pub const C5: Square = 2 + 4 * 8;
pub const D5: Square = 3 + 4 * 8;
pub const E5: Square = 4 + 4 * 8;
pub const F5: Square = 5 + 4 * 8;
pub const G5: Square = 6 + 4 * 8;
pub const H5: Square = 7 + 4 * 8;
pub const A6: Square = 0 + 5 * 8;
pub const B6: Square = 1 + 5 * 8;
pub const C6: Square = 2 + 5 * 8;
pub const D6: Square = 3 + 5 * 8;
pub const E6: Square = 4 + 5 * 8;
pub const F6: Square = 5 + 5 * 8;
pub const G6: Square = 6 + 5 * 8;
pub const H6: Square = 7 + 5 * 8;
pub const A7: Square = 0 + 6 * 8;
pub const B7: Square = 1 + 6 * 8;
pub const C7: Square = 2 + 6 * 8;
pub const D7: Square = 3 + 6 * 8;
pub const E7: Square = 4 + 6 * 8;
pub const F7: Square = 5 + 6 * 8;
pub const G7: Square = 6 + 6 * 8;
pub const H7: Square = 7 + 6 * 8;
pub const A8: Square = 0 + 7 * 8;
pub const B8: Square = 1 + 7 * 8;
pub const C8: Square = 2 + 7 * 8;
pub const D8: Square = 3 + 7 * 8;
pub const E8: Square = 4 + 7 * 8;
pub const F8: Square = 5 + 7 * 8;
pub const G8: Square = 6 + 7 * 8;
pub const H8: Square = 7 + 7 * 8;

/// Returns the square on given file and rank.
#[inline]
pub fn square(file: File, rank: Rank) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

/// Returns the rank of a given square.
#[inline(always)]
pub fn rank(square: Square) -> Rank {
    assert!(square <= 63);
    square >> 3
}

/// Returns the file of a given square.
#[inline(always)]
pub fn file(square: Square) -> File {
    assert!(square <= 63);
    square % 8
}

/// Returns the algebraic notation for a given square.
pub fn notation(square: Square) -> &'static str {
    lazy_static! {
        static ref NOTATION: Vec<String> = (0..64).map(|i| format!("{}{}",
            ["a", "b", "c", "d", "e", "f", "g", "h"][file(i)],
            ["1", "2", "3", "4", "5", "6", "7", "8"][rank(i)])
        ).collect();
    }
    NOTATION[square].as_str()
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use] extern crate log;

use std::collections::BTreeSet;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path,PathBuf};

use cargo::core::shell::{Verbosity, ColorConfig};
use cargo::util::{self, CliResult, lev_distance, Config, human, CargoResult};
use cargo::util::CliError;

#[derive(RustcDecodable)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_explain: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
    flag_locked: bool,
    flag_frozen: bool,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    --explain CODE      Run `rustc --explain CODE`
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date

Some common cargo commands are (see all commands with --list):
    build       Compile the current project
    check       Analyze the current project and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();

    let config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = cargo::shell(Verbosity::Verbose, ColorConfig::Auto);
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = (|| {
        let args: Vec<_> = try!(env::args_os().map(|s| {
            s.into_string().map_err(|s| {
                human(format!("invalid unicode in argument: {:?}", s))
            })
        }).collect());
        let rest = &args;
        cargo::call_main_without_stdin(execute, &config, USAGE, rest, true)
    })();

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {},
    }
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(check);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult {
    config.configure(flags.flag_verbose,
                     flags.flag_quiet,
                     &flags.flag_color,
                     flags.flag_frozen,
                     flags.flag_locked)?;

    init_git_transports(config);
    let _token = cargo::util::job::setup();

    if flags.flag_version {
        let version = cargo::version();
        println!("{}", version);
        if flags.flag_verbose > 0{
            println!("release: {}.{}.{}",
                     version.major, version.minor, version.patch);
            if let Some(ref cfg) = version.cfg_info {
                if let Some(ref ci) = cfg.commit_info {
                    println!("commit-hash: {}", ci.commit_hash);
                    println!("commit-date: {}", ci.commit_date);
                }
            }
        }
        return Ok(())
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        };
        return Ok(())
    }

    if let Some(ref code) = flags.flag_explain {
        let mut procss = config.rustc()?.process();
        procss.arg("--explain").arg(code).exec().map_err(human)?;
        return Ok(())
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbosity(Verbosity::Verbose);
            let args = &["cargo".to_string(), "-h".to_string()];
            return cargo::call_main_without_stdin(execute, config, USAGE, args, false);
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" ||
                  flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(),
                       "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => {
            let mut default_alias = HashMap::new();
            default_alias.insert("b", "build".to_string());
            default_alias.insert("t", "test".to_string());
            default_alias.insert("r", "run".to_string());
            let mut args: Vec<String> = env::args().collect();
            if let Some(new_command) = default_alias.get(&args[1][..]){
                args[1] = new_command.clone();
            }
            args
        }
    };

    if let Some(r) = try_execute_builtin_command(&config, &args) {
        return r;
    }

    let alias_list = aliased_command(&config, &args[1])?;
    let args = match alias_list {
        Some(alias_command) => {
            let chain = args.iter().take(1)
                .chain(alias_command.iter())
                .chain(args.iter().skip(2))
                .map(|s| s.to_string())
                .collect::<Vec<_>>();
            if let Some(r) = try_execute_builtin_command(&config, &chain) {
                return r;
            } else {
                chain
            }
        }
        None => args,
    };

    execute_external_subcommand(config, &args[1], &args)
}

fn try_execute_builtin_command(config: &Config, args: &[String]) -> Option<CliResult> {
    macro_rules! cmd {
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbosity(Verbosity::Verbose);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            return Some(r);
        })
    }
    each_subcommand!(cmd);

    None
}

fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record.val.split_whitespace()
                                               .map(|s| s.to_string())
                                               .collect();
                result = Ok(Some(alias_commands));
            }
        },
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> = record.val.iter()
                                .map(|s| s.0.to_string()).collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter().map(|c| (lev_distance(&c, cmd), c))
                                  .filter(|&(d, _)| d < 4)
                                  .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_external_subcommand(config: &Config,
                               cmd: &str,
                               args: &[String]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
                    .iter()
                    .map(|dir| dir.join(&command_exe))
                    .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            return Err(human(match find_closest(config, cmd) {
                Some(closest) => format!("no such subcommand: `{}`\n\n\t\
                                          Did you mean `{}`?\n", cmd, closest),
                None => format!("no such subcommand: `{}`", cmd)
            }).into())
        }
    };
    let err = match util::process(&command).args(&args[1..]).exec() {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(code) = err.exit.as_ref().and_then(|c| c.code()) {
        Err(CliError::code(code))
    } else {
        Err(CliError::new(Box::new(err), 101))
    }
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(filename[prefix.len()..end].to_string());
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path).map(|metadata| {
        metadata.is_file() && metadata.permissions().mode() & 0o111 != 0
    }).unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).map(|metadata| metadata.is_file()).unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>rustfmt for bin/cargo.rs<commit_after>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use]
extern crate log;

use std::collections::BTreeSet;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

use cargo::core::shell::{Verbosity, ColorConfig};
use cargo::util::{self, CliResult, lev_distance, Config, human, CargoResult};
use cargo::util::CliError;

#[derive(RustcDecodable)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_explain: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
    flag_locked: bool,
    flag_frozen: bool,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    --explain CODE      Run `rustc --explain CODE`
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date

Some common cargo commands are (see all commands with --list):
    build       Compile the current project
    check       Analyze the current project and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();

    let config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = cargo::shell(Verbosity::Verbose, ColorConfig::Auto);
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = (|| {
        let args: Vec<_> = try!(env::args_os()
            .map(|s| {
                s.into_string().map_err(|s| human(format!("invalid unicode in argument: {:?}", s)))
            })
            .collect());
        let rest = &args;
        cargo::call_main_without_stdin(execute, &config, USAGE, rest, true)
    })();

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(check);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult {
    config.configure(flags.flag_verbose,
                   flags.flag_quiet,
                   &flags.flag_color,
                   flags.flag_frozen,
                   flags.flag_locked)?;

    init_git_transports(config);
    let _token = cargo::util::job::setup();

    if flags.flag_version {
        let version = cargo::version();
        println!("{}", version);
        if flags.flag_verbose > 0 {
            println!("release: {}.{}.{}",
                     version.major,
                     version.minor,
                     version.patch);
            if let Some(ref cfg) = version.cfg_info {
                if let Some(ref ci) = cfg.commit_info {
                    println!("commit-hash: {}", ci.commit_hash);
                    println!("commit-date: {}", ci.commit_date);
                }
            }
        }
        return Ok(());
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        }
        return Ok(());
    }

    if let Some(ref code) = flags.flag_explain {
        let mut procss = config.rustc()?.process();
        procss.arg("--explain").arg(code).exec().map_err(human)?;
        return Ok(());
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbosity(Verbosity::Verbose);
            let args = &["cargo".to_string(), "-h".to_string()];
            return cargo::call_main_without_stdin(execute, config, USAGE, args, false);
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" || flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(), "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => {
            let mut default_alias = HashMap::new();
            default_alias.insert("b", "build".to_string());
            default_alias.insert("t", "test".to_string());
            default_alias.insert("r", "run".to_string());
            let mut args: Vec<String> = env::args().collect();
            if let Some(new_command) = default_alias.get(&args[1][..]) {
                args[1] = new_command.clone();
            }
            args
        }
    };

    if let Some(r) = try_execute_builtin_command(&config, &args) {
        return r;
    }

    let alias_list = aliased_command(&config, &args[1])?;
    let args = match alias_list {
        Some(alias_command) => {
            let chain = args.iter()
                .take(1)
                .chain(alias_command.iter())
                .chain(args.iter().skip(2))
                .map(|s| s.to_string())
                .collect::<Vec<_>>();
            if let Some(r) = try_execute_builtin_command(&config, &chain) {
                return r;
            } else {
                chain
            }
        }
        None => args,
    };

    execute_external_subcommand(config, &args[1], &args)
}

fn try_execute_builtin_command(config: &Config, args: &[String]) -> Option<CliResult> {
    macro_rules! cmd {
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbosity(Verbosity::Verbose);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            return Some(r);
        })
    }
    each_subcommand!(cmd);

    None
}

fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record.val
                    .split_whitespace()
                    .map(|s| s.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> = record.val
                    .iter()
                    .map(|s| s.0.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter()
        .map(|c| (lev_distance(&c, cmd), c))
        .filter(|&(d, _)| d < 4)
        .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[String]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            return Err(human(match find_closest(config, cmd) {
                    Some(closest) => {
                        format!("no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
                                cmd,
                                closest)
                    }
                    None => format!("no such subcommand: `{}`", cmd),
                })
                .into())
        }
    };
    let err = match util::process(&command).args(&args[1..]).exec() {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(code) = err.exit.as_ref().and_then(|c| c.code()) {
        Err(CliError::code(code))
    } else {
        Err(CliError::new(Box::new(err), 101))
    }
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(filename[prefix.len()..end].to_string());
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).map(|metadata| metadata.is_file()).unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>


<commit_before>extern crate argparse;
extern crate image;
extern crate path_tracer;

use argparse::{ArgumentParser, Store, Collect};
use path_tracer::*;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;

#[derive(Debug)]
enum ImageError {
    IoError(io::Error),
    BadFileError(String)
}
use ImageError::*;

impl From<io::Error> for ImageError {
    fn from(e: io::Error) -> ImageError {
        ImageError::IoError(e)
    }
}
type Result<T> = std::result::Result<T, ImageError>;

struct PartialImage {
    image : Vec<Vec<Vec3d>>,
    samples : i32,
}

impl PartialImage {
    fn empty() -> PartialImage {
        PartialImage { image: Vec::new(), samples: 0 }
    }

    // I'm totally unsure about whether this is taking additional copies.
    fn add(self, other: PartialImage) -> PartialImage {
        let image = if self.samples == 0 { other.image } else {
            // A nicer way to do this would be ideal. This may well be doing lots of boundchecks.
            let mut combined : Vec<Vec<Vec3d>> = self.image;
            for y in 0..combined.len() {
                for x in 0..combined[y].len() {
                    combined[y][x] = combined[y][x] + other.image[y][x];
                }
            }
            combined
        };
        let samples = self.samples + other.samples;
        PartialImage { image: image, samples: samples }
    }

    fn height(&self) -> usize {
        self.image.len()
    }
    fn width(&self) -> usize {
        self.image[0].len()
    }
}

fn load_file(name: &String) -> Result<PartialImage> {
    let mut result : Vec<Vec<Vec3d>> = Vec::new();
    let file = BufReader::new(try!(File::open(&name)));
    println!("Loading '{}'", name);
    let mut line_iter = file.lines();
    let first_line = try!(line_iter.next().unwrap());
    let first_line : Vec<usize> = first_line.split(' ').filter_map(|x| x.parse().ok()).collect();
    // Rust experimental branch would let us match on the vector.
    if first_line.len() != 3 { return Err(BadFileError("Bad header".to_string())); }
    let width = first_line[0];
    let height = first_line[1];
    let samples = first_line[2] as i32;
    println!("Found {} samples in {}x{} image", samples, width, height);
    for line in line_iter.filter_map(|x| x.ok()) {
        let mut vecs : Vec<Vec3d> = Vec::new();
        let mut split = line.split(' ').filter_map(|x| x.parse::<f64>().ok());
        loop {
            match (split.next(), split.next(), split.next()) {
                (None, _, _) => break,
                (Some(x), Some(y), Some(z)) => {
                    vecs.push(Vec3d::new(x, y, z) * samples as f64);
                },
                (_, _, _) => return Err(BadFileError("Bad line".to_string())),
            }
        }
        if vecs.len() != width {
            return Err(BadFileError("Bad width".to_string()));
        }
        result.push(vecs);
    }
    if result.len() != height {
        return Err(BadFileError("Bad height".to_string()));
    }
    println!("Loaded ok");
    Ok(PartialImage { image: result, samples: samples })
}

fn main() {
    let mut to_merge : Vec<String> = Vec::new();
    let mut output_filename = "image.png".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Combine several sample images into one PNG");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.refer(&mut to_merge).add_argument("files", Collect, "Files to merge")
            .required();
        ap.parse_args_or_exit();
    }
    let accum : PartialImage = to_merge.iter()
        .map(load_file)
        .map(|x| x.unwrap())
        .fold(PartialImage::empty(), |acc, item| { acc.add(item) });

    println!("Merged {} samples", accum.samples);
    println!("Writing output to '{}'", output_filename);
    let height = accum.height();
    let width = accum.width();
    let samples = accum.samples;
    let mut image = image::ImageBuffer::new(width as u32, height as u32);
    for y in 0..height {
        for x in 0..width {
            let sum = accum.image[y][x] / samples as f64;
            image.put_pixel(x as u32, y as u32, image::Rgb([to_int(sum.x), to_int(sum.y), to_int(sum.z)]));
        }
    }
    let mut output_file = File::create(output_filename).unwrap();
    image::ImageRgb8(image).save(&mut output_file, image::PNG).unwrap();
}
<commit_msg>More rustaceous iteration for merging<commit_after>extern crate argparse;
extern crate image;
extern crate path_tracer;

use argparse::{ArgumentParser, Store, Collect};
use path_tracer::*;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;

#[derive(Debug)]
enum ImageError {
    IoError(io::Error),
    BadFileError(String)
}
use ImageError::*;

impl From<io::Error> for ImageError {
    fn from(e: io::Error) -> ImageError {
        ImageError::IoError(e)
    }
}
type Result<T> = std::result::Result<T, ImageError>;

struct PartialImage {
    image : Vec<Vec<Vec3d>>,
    samples : i32,
}

impl PartialImage {
    fn empty() -> PartialImage {
        PartialImage { image: Vec::new(), samples: 0 }
    }

    fn add(self, other: PartialImage) -> PartialImage {
        let image = if self.samples == 0 { other.image } else {
            let combined = self.image.iter().zip(other.image.iter()).map(|(x, y)| {
                x.iter().zip(y.iter()).map(|(x, y)| { *x + *y }).collect()
            }).collect();
            combined
        };
        let samples = self.samples + other.samples;
        PartialImage { image: image, samples: samples }
    }

    fn height(&self) -> usize {
        self.image.len()
    }
    fn width(&self) -> usize {
        self.image[0].len()
    }
}

fn load_file(name: &String) -> Result<PartialImage> {
    let mut result : Vec<Vec<Vec3d>> = Vec::new();
    let file = BufReader::new(try!(File::open(&name)));
    println!("Loading '{}'", name);
    let mut line_iter = file.lines();
    let first_line = try!(line_iter.next().unwrap());
    let first_line : Vec<usize> = first_line.split(' ').filter_map(|x| x.parse().ok()).collect();
    // Rust experimental branch would let us match on the vector.
    if first_line.len() != 3 { return Err(BadFileError("Bad header".to_string())); }
    let width = first_line[0];
    let height = first_line[1];
    let samples = first_line[2] as i32;
    println!("Found {} samples in {}x{} image", samples, width, height);
    for line in line_iter.filter_map(|x| x.ok()) {
        let mut vecs : Vec<Vec3d> = Vec::new();
        let mut split = line.split(' ').filter_map(|x| x.parse::<f64>().ok());
        loop {
            match (split.next(), split.next(), split.next()) {
                (None, _, _) => break,
                (Some(x), Some(y), Some(z)) => {
                    vecs.push(Vec3d::new(x, y, z) * samples as f64);
                },
                (_, _, _) => return Err(BadFileError("Bad line".to_string())),
            }
        }
        if vecs.len() != width {
            return Err(BadFileError("Bad width".to_string()));
        }
        result.push(vecs);
    }
    if result.len() != height {
        return Err(BadFileError("Bad height".to_string()));
    }
    println!("Loaded ok");
    Ok(PartialImage { image: result, samples: samples })
}

fn main() {
    let mut to_merge : Vec<String> = Vec::new();
    let mut output_filename = "image.png".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Combine several sample images into one PNG");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.refer(&mut to_merge).add_argument("files", Collect, "Files to merge")
            .required();
        ap.parse_args_or_exit();
    }
    let accum : PartialImage = to_merge.iter()
        .map(load_file)
        .map(|x| x.unwrap())
        .fold(PartialImage::empty(), |acc, item| { acc.add(item) });

    println!("Merged {} samples", accum.samples);
    println!("Writing output to '{}'", output_filename);
    let height = accum.height();
    let width = accum.width();
    let samples = accum.samples;
    let mut image = image::ImageBuffer::new(width as u32, height as u32);
    for y in 0..height {
        for x in 0..width {
            let sum = accum.image[y][x] / samples as f64;
            image.put_pixel(x as u32, y as u32, image::Rgb([to_int(sum.x), to_int(sum.y), to_int(sum.z)]));
        }
    }
    let mut output_file = File::create(output_filename).unwrap();
    image::ImageRgb8(image).save(&mut output_file, image::PNG).unwrap();
}
<|endoftext|>


<commit_before>//! Defines the BSDF which acts as a container for composing the various BRDFs
//! and BTDFs that describe the surface's properties

use std::cmp;
use enum_set::EnumSet;

use linalg::{self, Normal, Vector, Point};
use film::Colorf;
use geometry::DifferentialGeometry;
use bxdf::{BxDF, BxDFType};
use sampler::Sample;

/// The BSDF contains the various BRDFs and BTDFs that describe the surface's properties
/// at some point. It also transforms incident and outgoing light directions into
/// shading space to make the BxDFs easier to implement.
/// TODO: We really need the memory pool. Each time we get the bsdf from a
/// material we need to allocate a decent amount of stuff since they each need
/// their own tangent, bitangent and differential geometry reference.
pub struct BSDF<'a> {
    /// The hit point
    pub p: Point,
    /// Shading normal, may be perturbed by bump mapping
    pub n: Normal,
    /// The actual geometry normal
    pub ng: Normal,
    /// Tangent vector for the surface
    pub tan: Vector,
    /// Bitangent vector for the surface
    pub bitan: Vector,
    /// Refractive index of the geometry
    pub eta: f32,
    /// TODO: Currently a Vec is safe to use but once in the memory pool it
    /// will leak since it won't be dropped. This would also migrate our BxDFs
    /// from Box<BxDF> to &BxDF. When unboxed traits land we can move to unboxed
    /// BxDFs here though.
    bxdfs: &'a [Box<BxDF + Send + Sync>],
}

impl<'a> BSDF<'a> {
    /// Create a new BSDF using the BxDFs passed to shade the differential geometry with
    /// refractive index `eta`
    pub fn new(bxdfs: &'a [Box<BxDF + Send + Sync>], eta: f32,
               dg: &DifferentialGeometry<'a>)
               -> BSDF<'a> {
        let n = dg.n.normalized();
        let mut bitan = dg.dp_du.normalized();
        let tan = linalg::cross(&n, &bitan);
        bitan = linalg::cross(&tan, &n);
        BSDF { p: dg.p, n: n, ng: dg.ng, tan: tan, bitan: bitan, bxdfs: bxdfs, eta: eta }
    }
    /// Return the total number of BxDFs
    pub fn num_bxdfs(&self) -> usize { self.bxdfs.len() }
    /// Return the number of BxDFs matching the flags
    pub fn num_matching(&self, flags: EnumSet<BxDFType>) -> usize {
        self.bxdfs.iter().filter(|ref x| x.matches(flags)).count()
    }
    /// Transform the vector from world space to shading space
    pub fn to_shading(&self, v: &Vector) -> Vector {
        Vector::new(linalg::dot(v, &self.bitan), linalg::dot(v, &self.tan),
                    linalg::dot(v, &self.n))
    }
    /// Transform the vectro from shading space to world space
    pub fn from_shading(&self, v: &Vector) -> Vector {
        Vector::new(self.bitan.x * v.x + self.tan.x * v.y + self.n.x * v.z,
                    self.bitan.y * v.x + self.tan.y * v.y + self.n.y * v.z,
                    self.bitan.z * v.x + self.tan.z * v.y + self.n.z * v.z)
    }
    /// Evaluate the BSDF for the outgoing and incident light directions
    /// `w_o` and `w_i` in world space, sampling the desired subset of BxDFs
    /// selected by the flags passed. `wo_world` and `wi_world` should point from
    /// the hit point in the outgoing and incident light directions respectively.
    pub fn eval(&self, wo_world: &Vector, wi_world: &Vector, mut flags: EnumSet<BxDFType>) -> Colorf {
        let w_o = self.to_shading(wo_world);
        let w_i = self.to_shading(wi_world);
        // Determine if we should evaluate reflection or transmission based on the
        // geometry normal and the light directions
        if linalg::dot(wo_world, &self.ng) * linalg::dot(wi_world, &self.ng) > 0.0 {
            flags.remove(&BxDFType::Transmission);
        } else {
            flags.remove(&BxDFType::Reflection);
        }
        // Find all matching BxDFs and add their contribution to the material's color
        self.bxdfs.iter().filter_map(|ref x| if x.matches(flags) { Some(x.eval(&w_o, &w_i)) } else { None })
            .fold(Colorf::broadcast(0.0), |x, y| x + y)
    }
    /// Sample a component of the BSDF to get an incident light direction for light
    /// leaving the surface along `w_o`.
    /// `samples` are the 3 random values to use when sampling a component of the BSDF
    /// and a the chosen BSDF
    /// Returns the color, direction, pdf and the type of BxDF that was sampled.
    pub fn sample(&self, wo_world: &Vector, flags: EnumSet<BxDFType>, samples: &Sample)
        -> (Colorf, Vector, f32, EnumSet<BxDFType>) {
        let n_matching = self.num_matching(flags);
        if n_matching == 0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let comp = cmp::min((samples.one_d * n_matching as f32) as usize, n_matching - 1);
        let bxdf = self.matching_at(comp, flags);
        let w_o = self.to_shading(wo_world).normalized();
        let (mut f, w_i, mut pdf) = bxdf.sample(&w_o, &samples.two_d);
        if w_i.length_sqr() == 0.0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }

        let wi_world = self.from_shading(&w_i).normalized();
        // TODO: We re-use our functions but actually do a lot of redundant computation. I'm not
        // sure that the compiler will eliminate it. Should just copy in the code from pdf and eval
        if !bxdf.bxdf_type().contains(&BxDFType::Specular) && n_matching > 1 {
            pdf = self.pdf(wo_world, &wi_world, flags);
        }
        if n_matching > 1 {
            pdf /= n_matching as f32;
        }

        if !bxdf.bxdf_type().contains(&BxDFType::Specular) {
            f = self.eval(wo_world, &wi_world, flags);
        }
        (f, wi_world, pdf, bxdf.bxdf_type())
    }
    /// Compute the pdf for sampling the pair of incident and outgoing light directions for
    /// the BxDFs matching the flags set
    pub fn pdf(&self, wo_world: &Vector, wi_world: &Vector, flags: EnumSet<BxDFType>) -> f32 {
        let w_o = self.to_shading(wo_world);
        let w_i = self.to_shading(wi_world);
        let (pdf_val, n_comps) = self.bxdfs.iter()
            .filter_map(|ref x| if x.matches(flags) { Some(x.pdf(&w_o, &w_i)) } else { None })
            .fold((0.0, 0), |(p, n), y| (p + y, n + 1));
        if n_comps > 0 {
            pdf_val / n_comps as f32
        } else {
            0.0
        }
    }
    /// Get the `i`th BxDF that matches the flags passed. There should not be fewer than i
    /// BxDFs that match the flags
    fn matching_at(&self, i: usize, flags: EnumSet<BxDFType>) -> &Box<BxDF + Send + Sync> {
        let mut it = self.bxdfs.iter().filter(|ref x| x.matches(flags)).skip(i);
        match it.next() {
            Some(b) => b,
            None => panic!("Out of bounds index for BxDF type {:?}", flags)
        }
    }
}

<commit_msg>missed some normalizing<commit_after>//! Defines the BSDF which acts as a container for composing the various BRDFs
//! and BTDFs that describe the surface's properties

use std::cmp;
use enum_set::EnumSet;

use linalg::{self, Normal, Vector, Point};
use film::Colorf;
use geometry::DifferentialGeometry;
use bxdf::{BxDF, BxDFType};
use sampler::Sample;

/// The BSDF contains the various BRDFs and BTDFs that describe the surface's properties
/// at some point. It also transforms incident and outgoing light directions into
/// shading space to make the BxDFs easier to implement.
/// TODO: We really need the memory pool. Each time we get the bsdf from a
/// material we need to allocate a decent amount of stuff since they each need
/// their own tangent, bitangent and differential geometry reference.
pub struct BSDF<'a> {
    /// The hit point
    pub p: Point,
    /// Shading normal, may be perturbed by bump mapping
    pub n: Normal,
    /// The actual geometry normal
    pub ng: Normal,
    /// Tangent vector for the surface
    pub tan: Vector,
    /// Bitangent vector for the surface
    pub bitan: Vector,
    /// Refractive index of the geometry
    pub eta: f32,
    /// TODO: Currently a Vec is safe to use but once in the memory pool it
    /// will leak since it won't be dropped. This would also migrate our BxDFs
    /// from Box<BxDF> to &BxDF. When unboxed traits land we can move to unboxed
    /// BxDFs here though.
    bxdfs: &'a [Box<BxDF + Send + Sync>],
}

impl<'a> BSDF<'a> {
    /// Create a new BSDF using the BxDFs passed to shade the differential geometry with
    /// refractive index `eta`
    pub fn new(bxdfs: &'a [Box<BxDF + Send + Sync>], eta: f32,
               dg: &DifferentialGeometry<'a>)
               -> BSDF<'a> {
        let n = dg.n.normalized();
        let mut bitan = dg.dp_du.normalized();
        let tan = linalg::cross(&n, &bitan);
        bitan = linalg::cross(&tan, &n);
        BSDF { p: dg.p, n: n, ng: dg.ng, tan: tan, bitan: bitan, bxdfs: bxdfs, eta: eta }
    }
    /// Return the total number of BxDFs
    pub fn num_bxdfs(&self) -> usize { self.bxdfs.len() }
    /// Return the number of BxDFs matching the flags
    pub fn num_matching(&self, flags: EnumSet<BxDFType>) -> usize {
        self.bxdfs.iter().filter(|ref x| x.matches(flags)).count()
    }
    /// Transform the vector from world space to shading space
    pub fn to_shading(&self, v: &Vector) -> Vector {
        Vector::new(linalg::dot(v, &self.bitan), linalg::dot(v, &self.tan),
                    linalg::dot(v, &self.n))
    }
    /// Transform the vectro from shading space to world space
    pub fn from_shading(&self, v: &Vector) -> Vector {
        Vector::new(self.bitan.x * v.x + self.tan.x * v.y + self.n.x * v.z,
                    self.bitan.y * v.x + self.tan.y * v.y + self.n.y * v.z,
                    self.bitan.z * v.x + self.tan.z * v.y + self.n.z * v.z)
    }
    /// Evaluate the BSDF for the outgoing and incident light directions
    /// `w_o` and `w_i` in world space, sampling the desired subset of BxDFs
    /// selected by the flags passed. `wo_world` and `wi_world` should point from
    /// the hit point in the outgoing and incident light directions respectively.
    pub fn eval(&self, wo_world: &Vector, wi_world: &Vector, mut flags: EnumSet<BxDFType>) -> Colorf {
        let w_o = self.to_shading(wo_world);
        let w_i = self.to_shading(wi_world);
        // Determine if we should evaluate reflection or transmission based on the
        // geometry normal and the light directions
        if linalg::dot(wo_world, &self.ng) * linalg::dot(wi_world, &self.ng) > 0.0 {
            flags.remove(&BxDFType::Transmission);
        } else {
            flags.remove(&BxDFType::Reflection);
        }
        // Find all matching BxDFs and add their contribution to the material's color
        self.bxdfs.iter().filter_map(|ref x| if x.matches(flags) { Some(x.eval(&w_o, &w_i)) } else { None })
            .fold(Colorf::broadcast(0.0), |x, y| x + y)
    }
    /// Sample a component of the BSDF to get an incident light direction for light
    /// leaving the surface along `w_o`.
    /// `samples` are the 3 random values to use when sampling a component of the BSDF
    /// and a the chosen BSDF
    /// Returns the color, direction, pdf and the type of BxDF that was sampled.
    pub fn sample(&self, wo_world: &Vector, flags: EnumSet<BxDFType>, samples: &Sample)
        -> (Colorf, Vector, f32, EnumSet<BxDFType>) {
        let n_matching = self.num_matching(flags);
        if n_matching == 0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }
        let comp = cmp::min((samples.one_d * n_matching as f32) as usize, n_matching - 1);
        let bxdf = self.matching_at(comp, flags);
        let w_o = self.to_shading(wo_world).normalized();
        let (mut f, w_i, mut pdf) = bxdf.sample(&w_o, &samples.two_d);
        if w_i.length_sqr() == 0.0 {
            return (Colorf::broadcast(0.0), Vector::broadcast(0.0), 0.0, EnumSet::new());
        }

        let wi_world = self.from_shading(&w_i).normalized();
        // TODO: We re-use our functions but actually do a lot of redundant computation. I'm not
        // sure that the compiler will eliminate it. Should just copy in the code from pdf and eval
        if !bxdf.bxdf_type().contains(&BxDFType::Specular) && n_matching > 1 {
            pdf = self.pdf(wo_world, &wi_world, flags);
        }
        if n_matching > 1 {
            pdf /= n_matching as f32;
        }

        if !bxdf.bxdf_type().contains(&BxDFType::Specular) {
            f = self.eval(wo_world, &wi_world, flags);
        }
        (f, wi_world, pdf, bxdf.bxdf_type())
    }
    /// Compute the pdf for sampling the pair of incident and outgoing light directions for
    /// the BxDFs matching the flags set
    pub fn pdf(&self, wo_world: &Vector, wi_world: &Vector, flags: EnumSet<BxDFType>) -> f32 {
        // should also normalize?
        let w_o = self.to_shading(wo_world).normalized();
        let w_i = self.to_shading(wi_world).normalized();
        let (pdf_val, n_comps) = self.bxdfs.iter()
            .filter_map(|ref x| if x.matches(flags) { Some(x.pdf(&w_o, &w_i)) } else { None })
            .fold((0.0, 0), |(p, n), y| (p + y, n + 1));
        if n_comps > 0 {
            pdf_val / n_comps as f32
        } else {
            0.0
        }
    }
    /// Get the `i`th BxDF that matches the flags passed. There should not be fewer than i
    /// BxDFs that match the flags
    fn matching_at(&self, i: usize, flags: EnumSet<BxDFType>) -> &Box<BxDF + Send + Sync> {
        let mut it = self.bxdfs.iter().filter(|ref x| x.matches(flags)).skip(i);
        match it.next() {
            Some(b) => b,
            None => panic!("Out of bounds index for BxDF type {:?}", flags)
        }
    }
}

<|endoftext|>


<commit_before>//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};

use compositor;
use super::keys;
use super::lua;
use super::keys::KeyPress;
use super::layout::tree;

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    match tree::add_output(output) {
        Ok(_) => true,
        Err(_) => false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
             output, *old_size_ptr, *new_size_ptr);
}
/*
pub extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

pub extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}
*/
pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    let output = view.get_output();
    match tree::add_view(view.clone()) {
        Ok(_) => {},
        Err(_) => {
            // This causes view_destroyed to be called, might cause an issue
            view.close();
            return false;
        }
    }
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    return true;
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    match tree::remove_view(&view) {
        Ok(_) => {},
        Err(_) => {},
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    trace!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(EDGE_NONE, geometry);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    trace!("view_request_state: {}, {:?}, handled: {}",
    view.get_title(), state, handled);
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    // Called by views when they have a dang resize mouse thing, we should only
    // let it happen in view floating mode
    compositor::start_interactive_move(&view, dest);
    trace!("view_request_move: to {}", *dest);
}

pub extern fn view_request_resize(view: WlcView,
                              edge: ResizeEdge, location: &Point) {
    compositor::start_interactive_resize(&view, edge, location);
    trace!("view_request_resize: edge {:?}, to {}",
             edge, location);
}

pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    if state == KeyState::Pressed {
        // TODO this function will throw an error in Rustwlc right now
        // let mut keys = keyboard::get_current_keys().into_iter()
        //      .map(|&k| Keysym::from(k)).collect();
        let sym = keyboard::get_keysym_for_key(key, &KeyMod::empty());
        let keys = vec![sym];

        // Don't spam the console if a key isn't being pressed.
        if mods.mods.is_empty() || keys.len() == 1 {
            return EVENT_PASS_THROUGH;
        }

        let press = KeyPress::new(mods.mods, keys);
        trace!("keypress: {:?}", press);

        if let Some(action) = keys::get(&press) {
            info!("[key] Found a key!");
            action();
            return EVENT_HANDLED;
        }
        else {
            trace!("keypress: No callback");
        }
    }

    return EVENT_PASS_THROUGH;
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    compositor::on_pointer_button(view, _time, mods, button, state, point)
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [f64; 2]) -> bool {
    trace!("pointer_scroll: {:?} {:?}", axis,
           heights.iter().map(|f| f.clone().round()).collect::<Vec<f64>>());
    false
}

pub extern fn pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    pointer::set_position(point);
    compositor::on_pointer_motion(_view, _time, point)
}

/*
pub extern fn touch(view: WlcView, time: u32, mods_ptr: &KeyboardModifiers,
               touch: TouchType, key: i32, point_ptr: &Point) -> bool {
    false
}
*/

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<commit_msg>Reduce spam from keybinding callback<commit_after>//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};

use compositor;
use super::keys;
use super::lua;
use super::keys::KeyPress;
use super::layout::tree;

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    match tree::add_output(output) {
        Ok(_) => true,
        Err(_) => false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
             output, *old_size_ptr, *new_size_ptr);
}
/*
pub extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

pub extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}
*/
pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    let output = view.get_output();
    match tree::add_view(view.clone()) {
        Ok(_) => {},
        Err(_) => {
            // This causes view_destroyed to be called, might cause an issue
            view.close();
            return false;
        }
    }
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    return true;
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    match tree::remove_view(&view) {
        Ok(_) => {},
        Err(_) => {},
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    trace!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(EDGE_NONE, geometry);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    trace!("view_request_state: {}, {:?}, handled: {}",
    view.get_title(), state, handled);
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    // Called by views when they have a dang resize mouse thing, we should only
    // let it happen in view floating mode
    compositor::start_interactive_move(&view, dest);
    trace!("view_request_move: to {}", *dest);
}

pub extern fn view_request_resize(view: WlcView,
                              edge: ResizeEdge, location: &Point) {
    compositor::start_interactive_resize(&view, edge, location);
    trace!("view_request_resize: edge {:?}, to {}",
             edge, location);
}

pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    if state == KeyState::Pressed {
        // TODO this function will throw an error in Rustwlc right now
        // let mut keys = keyboard::get_current_keys().into_iter()
        //      .map(|&k| Keysym::from(k)).collect();
        let sym = keyboard::get_keysym_for_key(key, &KeyMod::empty());
        let keys = vec![sym];

        let press = KeyPress::new(mods.mods, keys);
        if let Some(action) = keys::get(&press) {
            info!("[key] Found an action for {:?}", press);
            action();
            return EVENT_HANDLED;
        }
    }

    return EVENT_PASS_THROUGH;
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    compositor::on_pointer_button(view, _time, mods, button, state, point)
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [f64; 2]) -> bool {
    trace!("pointer_scroll: {:?} {:?}", axis,
           heights.iter().map(|f| f.clone().round()).collect::<Vec<f64>>());
    false
}

pub extern fn pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    pointer::set_position(point);
    compositor::on_pointer_motion(_view, _time, point)
}

/*
pub extern fn touch(view: WlcView, time: u32, mods_ptr: &KeyboardModifiers,
               touch: TouchType, key: i32, point_ptr: &Point) -> bool {
    false
}
*/

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<|endoftext|>