<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate docopt;
extern crate mazes;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use docopt::Docopt;

use mazes::squaregrid::{GridCoordinate, GridDisplay, SquareGrid};
use mazes::generators;
use mazes::renderers;
use mazes::pathing;

const USAGE: &'static str = "Mazes

Usage:
    mazes_driver -h | --help
    mazes_driver [--grid-size=<n>]
    mazes_driver render (binary|sidewinder) [text --text-out=<path> --furthest-point (--path-start-x=<x> --path-start-y=<y>)] [image --image-out=<path> --cell-pixels=<n> --screen-view] [--grid-size=<n>]

Options:
    -h --help           Show this screen.
    --grid-size=<n>     The grid size is n * n [default: 20].
    --text-out=<path>   Output file path for a textual rendering of a maze.
    --path-start-x=<x>
    --path-start-y=<y>
    --furthest-point    Show the furthest (points) from the path-start-x/path-start-y coordinate
    --image-out=<path>  Output file path for an image rendering of a maze.
    --cell-pixels=<n>   Pixel count to render one cell wall in a maze [default: 10] max 255.
    --screen-view       When rendering to an image and saving to a file, also show the image on the screen.
";
#[derive(RustcDecodable, Debug)]
struct MazeArgs {
    flag_grid_size: u32,
    cmd_render: bool,
    cmd_binary: bool,
    cmd_sidewinder: bool,
    cmd_text: bool,
    flag_text_out: String,
    cmd_image: bool,
    flag_image_out: String,
    flag_cell_pixels: u8,
    flag_screen_view: bool,
    flag_furthest_point: bool,
    flag_path_start_x: Option<u32>,
    flag_path_start_y: Option<u32>,
}

fn main() {

    let args: MazeArgs = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());

    let grid_size = args.flag_grid_size;
    let any_render_option = args.cmd_text || args.cmd_image;

    // Do whatever defaults we want if not given a specific 'render' command
    let do_image_render = !args.cmd_render || args.cmd_image ||
                          (!any_render_option && grid_size >= 25);
    let do_text_render = args.cmd_render &&
                         (args.cmd_text || (!any_render_option && grid_size < 25));

    let mut maze_grid = SquareGrid::<u32>::new(grid_size);

    if args.cmd_render {
        if args.cmd_binary {
            generators::binary_tree(&mut maze_grid);
        }
        if args.cmd_sidewinder {
            generators::sidewinder(&mut maze_grid);
        }
    } else {
        generators::sidewinder(&mut maze_grid);
    }

    if do_text_render {
        if let (Some(x), Some(y)) = (args.flag_path_start_x, args.flag_path_start_y) {

            let distances = Rc::new(pathing::DijkstraDistances::<u32>::new(&maze_grid, GridCoordinate::new(x, y))
                    .unwrap_or_else(|| exit_with_msg("Provided invalid start coordinate from which to show path distances.")));

            if args.flag_furthest_point {

                let end_points = pathing::furthest_points_on_grid(&maze_grid, &distances);
                let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(GridCoordinate::new(x, y),
                                                                                end_points));
                maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
            } else {
                maze_grid.set_grid_display(Some(distances.clone() as Rc<GridDisplay>));
            }
        }

        if args.flag_text_out.is_empty() {
            println!("{}", maze_grid);
        } else {
            write_text_to_file(&format!("{}", maze_grid), &args.flag_text_out)
                .expect(&format!("Failed to write maze to text file {}", args.flag_text_out));
        }
    }
    if do_image_render {
        let is_image_path_set = !args.flag_image_out.is_empty();
        let out_image_path = if is_image_path_set {
            Some(Path::new(&args.flag_image_out))
        } else {
            None
        };
        let render_opts = renderers::RenderOptions::new(args.flag_screen_view ||
                                                        !is_image_path_set,
                                                        out_image_path,
                                                        args.flag_cell_pixels);
        renderers::render_square_grid(&maze_grid, &render_opts);
    }
}

fn write_text_to_file(data: &str, file_name: &str) -> io::Result<()> {
    let mut f = try!(File::create(file_name));
    try!(f.write_all(data.as_bytes()));
    Ok(())
}

fn exit_with_msg(e: &str) -> ! {
    writeln!(&mut io::stderr(), "{}", e).expect(format!("Failed to print error: {}", e).as_str());
    exit(1);
}
<commit_msg>Start shortest path text render.<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate docopt;
extern crate mazes;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use docopt::Docopt;

use mazes::squaregrid::{GridCoordinate, GridDisplay, SquareGrid};
use mazes::generators;
use mazes::renderers;
use mazes::pathing;

const USAGE: &'static str = "Mazes

Usage:
    mazes_driver -h | --help
    mazes_driver [--grid-size=<n>]
    mazes_driver render (binary|sidewinder) [text --text-out=<path> (--furthest-point|--end-point-x=<e1> --end-point-y=<e2>) (--path-start-x=<x> --path-start-y=<y>)] [image --image-out=<path> --cell-pixels=<n> --screen-view] [--grid-size=<n>]

Options:
    -h --help           Show this screen.
    --grid-size=<n>     The grid size is n * n [default: 20].
    --text-out=<path>   Output file path for a textual rendering of a maze.
    --path-start-x=<x>
    --path-start-y=<y>
    --end-point-x=<e1>
    --end-point-y=<e2>
    --furthest-point    Show the furthest (points) from the path-start-x/path-start-y coordinate
    --image-out=<path>  Output file path for an image rendering of a maze.
    --cell-pixels=<n>   Pixel count to render one cell wall in a maze [default: 10] max 255.
    --screen-view       When rendering to an image and saving to a file, also show the image on the screen.
";
#[derive(RustcDecodable, Debug)]
struct MazeArgs {
    flag_grid_size: u32,
    cmd_render: bool,
    cmd_binary: bool,
    cmd_sidewinder: bool,
    cmd_text: bool,
    flag_text_out: String,
    cmd_image: bool,
    flag_image_out: String,
    flag_cell_pixels: u8,
    flag_screen_view: bool,
    flag_furthest_point: bool,
    flag_path_start_x: Option<u32>,
    flag_path_start_y: Option<u32>,
    flag_end_point_x: Option<u32>,
    flag_end_point_y: Option<u32>,
}

fn main() {

    let args: MazeArgs = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());

    let grid_size = args.flag_grid_size;
    let any_render_option = args.cmd_text || args.cmd_image;

    // Do whatever defaults we want if not given a specific 'render' command
    let do_image_render = !args.cmd_render || args.cmd_image ||
                          (!any_render_option && grid_size >= 25);
    let do_text_render = args.cmd_render &&
                         (args.cmd_text || (!any_render_option && grid_size < 25));

    let mut maze_grid = SquareGrid::<u32>::new(grid_size);

    if args.cmd_render {
        if args.cmd_binary {
            generators::binary_tree(&mut maze_grid);
        }
        if args.cmd_sidewinder {
            generators::sidewinder(&mut maze_grid);
        }
    } else {
        generators::sidewinder(&mut maze_grid);
    }

    if do_text_render {
        if let (Some(x), Some(y)) = (args.flag_path_start_x, args.flag_path_start_y) {

            let distances = Rc::new(pathing::DijkstraDistances::<u32>::new(&maze_grid, GridCoordinate::new(x, y))
                    .unwrap_or_else(|| exit_with_msg("Provided invalid start coordinate from which to show path distances.")));

            if let (Some(end_x), Some(end_y)) = (args.flag_end_point_x, args.flag_end_point_y) {

                let path = pathing::shortest_path(&maze_grid, &distances, GridCoordinate::new(end_x, end_y));
                // turn into hashset for render_cell_body display routine?
            }
            else if args.flag_furthest_point {

                let end_points = pathing::furthest_points_on_grid(&maze_grid, &distances);
                let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(GridCoordinate::new(x, y),
                                                                                end_points));
                maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
            } else {

                maze_grid.set_grid_display(Some(distances.clone() as Rc<GridDisplay>));
            }
        }

        if args.flag_text_out.is_empty() {
            println!("{}", maze_grid);
        } else {
            write_text_to_file(&format!("{}", maze_grid), &args.flag_text_out)
                .expect(&format!("Failed to write maze to text file {}", args.flag_text_out));
        }
    }
    if do_image_render {
        let is_image_path_set = !args.flag_image_out.is_empty();
        let out_image_path = if is_image_path_set {
            Some(Path::new(&args.flag_image_out))
        } else {
            None
        };
        let render_opts = renderers::RenderOptions::new(args.flag_screen_view ||
                                                        !is_image_path_set,
                                                        out_image_path,
                                                        args.flag_cell_pixels);
        renderers::render_square_grid(&maze_grid, &render_opts);
    }
}

fn write_text_to_file(data: &str, file_name: &str) -> io::Result<()> {
    let mut f = try!(File::create(file_name));
    try!(f.write_all(data.as_bytes()));
    Ok(())
}

fn exit_with_msg(e: &str) -> ! {
    writeln!(&mut io::stderr(), "{}", e).expect(format!("Failed to print error: {}", e).as_str());
    exit(1);
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate find_folder;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate gfx;
extern crate vecmath;
extern crate image as im;
extern crate time;

use piston_window::*;
use time::{Duration, PreciseTime};

mod creature;
mod player;
mod io;
mod level;
mod inventory;
mod item;
mod actor;
mod field;
mod interactable;
mod coord;
mod enums;
mod camera;

use camera::{Cam, Range};
use player::{Player, LastKey};
use creature::Creature;
use field::Field;
use interactable::Interactable;
use coord::Coordinate;
use io::{render_level, read_level, render_tile};
use io::tileset::{TILE_HEIGHT, TILE_WIDTH, Tileset};
use level::Level;

//EINGABEN
const TWO_PLAYER: bool = true;
const SPRITE_P_1: &'static str = "warrior2.png";
const SPRITE_P_2: &'static str = "paladin.png";
const CAMERA_BUF_X: u64 = 4;
const CAMERA_BUF_Y: u64 = 4;

const WIDTH: i64 = 1600;
const HEIGHT: i64 = 900;

const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub struct App {
    player_one: Player,
    player_two: Option<Player>,
    cam: Cam,
}

impl App {
    fn new(two_player: bool) -> Self {
        App {
            // 0,0 Dummy-Value
            player_one: Player::new(0, 0),
            player_two: if two_player {
                // 0,0 Dummy-Value
                Some(Player::new(0, 0))
            } else {
                None
            },
            cam: Cam::new(CAMERA_BUF_X, CAMERA_BUF_Y),
        }
    }

    fn on_draw(&mut self,
               args: &RenderArgs,
               mut w: &mut PistonWindow,
               e: &Event,
               tileset: &Tileset,
               mut level: &mut Level) {
        let player_one = &self.player_one.creature;
        let player_two = &self.player_two;
        let coord1 = self.player_one.coord.clone();
        let mut coord2 = coord1.clone();
        self.cam.calc_coordinates(coord1, coord2);
        let range = self.cam.get_range();
        w.draw_2d(e, |c, gl| {
            // Clear the screen.
            clear(BLACK, gl);
            let center_p1 = c.transform.trans((self.player_one.coord.get_x() * 65) as f64,
                                              (self.player_one.coord.get_y() * 65) as f64);
            let center_lv = c.transform.trans(0.0, 0.0);

            //render_level(&tileset, gl, center_lv, &mut level);
            for i in range.x_min..range.x_max {
                for j in range.y_min..range.y_max {
                    let tile = match tileset.get_texture(level.get_data()[i as usize][j as usize].get_id()) {
                    Some(x) => x,
                    None => panic!("No texture found."),
                    };
                    // DEBUG
                    //println!("{} {}", i, j);
                    render_tile(&tile, gl, center_lv,  j as u32 * TILE_HEIGHT,
                            i as u32 * TILE_WIDTH,
                            i as u32,
                            j as u32);

                }
            }

            player_one.render(gl, center_p1);
            if let Some(ref x) = *player_two {
                x.creature.render(gl, center_p1);
            }
        });
    }

    fn on_update(&mut self,
                 args: &UpdateArgs,) {

        self.player_one.on_update(args);
        if let Some(ref mut x) = self.player_two {

            x.on_update(args);
        }

    }

    fn on_input(&mut self, inp: Button, pressed: bool) {

        match inp {
            Button::Keyboard(Key::Up) => {
                if pressed {
                    self.player_one.last = LastKey::Up;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Down) => {
                if pressed {
                    self.player_one.last = LastKey::Down;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Left) => {
                if pressed {
                    self.player_one.last = LastKey::Left;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Right) => {
                if pressed {
                    self.player_one.last = LastKey::Right;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::W) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Up;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::S) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Down;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::A) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Left;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::D) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Right;
                    }
                    x.pressed = pressed;
                }
            }
            _ => {}

        }
    }
    fn on_load(&mut self, mut w: &mut PistonWindow) {
        let mut player_one = &mut self.player_one;
        App::load_sprite(w, &mut player_one, SPRITE_P_1);
        if let Some(ref mut x) = self.player_two {
            App::load_sprite(w, x, SPRITE_P_2);
        }

    }
    fn load_sprite(mut w: &mut PistonWindow, player: &mut Player, file: &str) {
        let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
        let tank_sprite = assets.join(file);
        let tank_sprite2 = Texture::from_path(&mut w.factory,
                                              &tank_sprite,
                                              Flip::None,
                                              &TextureSettings::new());
        match tank_sprite2 {
            Err(_) => {
                println!("Empty");
            }
            Ok(x) => {
                player.creature.set_sprite(x);
            }
        }

    }
}

fn main() {
    // Create an Glutin window.
    let mut window: PistonWindow = WindowSettings::new("spinning-square",
                                                       [WIDTH as u32, HEIGHT as u32])
        .exit_on_esc(true)
        //.fullscreen(true)
        .build()
        .unwrap();

    // Create a new game and run it.

    let mut app = App::new(TWO_PLAYER);
    app.on_load(&mut window);

    let mut events = window.events();

    let folder = match find_folder::Search::Kids(1).for_folder("tiles") {
        Ok(res) => res.join("tileset-pokemon_dawn.png"),
        Err(_) => panic!("Folder 'tiles' not found!"),
    };

    let file_path = match folder.to_str() {
        Some(res) => res,
        None => panic!("Tileset not found!"),
    };

    let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
        Ok(res) => res.join("level1.lvl"),
        Err(_) => panic!("Folder 'src' not found!"),
    };

    let level_path = match folder_level.to_str() {
        Some(res) => res,
        None => panic!("Level not found!"),
    };

    let tileset = io::read_tileset(file_path, &mut window);

    let mut level = io::read_level(level_path);

    let mut start = PreciseTime::now();
    app.cam.set_borders((level.get_x() as u64, level.get_y()as u64));

    while let Some(e) = events.next(&mut window) {
        let now = start.to(PreciseTime::now()).num_milliseconds();
        //println!("{}", now);

        if let Some(r) = e.render_args() {
            app.on_draw(&r, &mut window, &e, &tileset, &mut level);
        }
        if let Some(i) = e.release_args() {
            app.on_input(i, false);
        }
        if let Some(i) = e.press_args() {
            app.on_input(i, true);
        }
        if now > 500 {
            if let Some(u) = e.update_args() {
                app.on_update(&u);
                start = PreciseTime::now();
            }
        }

    }

}

//UTIL//////////////////////////////

fn border_add(add1: f64, add2: f64, width: bool) -> f64 {
    let border = (if width { WIDTH } else { HEIGHT }) as f64;
    let sum = add1 + add2;
    if sum < 0.0 {
        0.0
    } else if sum > border {
        border
    } else {
        sum
    }
}
<commit_msg>Some minor fixes for camera<commit_after>extern crate piston_window;
extern crate find_folder;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate gfx;
extern crate vecmath;
extern crate image as im;
extern crate time;

use piston_window::*;
use time::{Duration, PreciseTime};

mod creature;
mod player;
mod io;
mod level;
mod inventory;
mod item;
mod actor;
mod field;
mod interactable;
mod coord;
mod enums;
mod camera;

use camera::{Cam, Range};
use player::{Player, LastKey};
use creature::Creature;
use field::Field;
use interactable::Interactable;
use coord::Coordinate;
use io::{render_level, read_level, render_tile};
use io::tileset::{TILE_HEIGHT, TILE_WIDTH, Tileset};
use level::Level;

//EINGABEN
const TWO_PLAYER: bool = true;
const SPRITE_P_1: &'static str = "warrior2.png";
const SPRITE_P_2: &'static str = "paladin.png";
const CAMERA_BUF_X: u64 = 4;
const CAMERA_BUF_Y: u64 = 4;

const WIDTH: i64 = 1600;
const HEIGHT: i64 = 900;

const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub struct App {
    player_one: Player,
    player_two: Option<Player>,
    cam: Cam,
}

impl App {
    fn new(two_player: bool) -> Self {
        App {
            // 0,0 Dummy-Value
            player_one: Player::new(0, 0),
            player_two: if two_player {
                // 0,0 Dummy-Value
                Some(Player::new(0, 0))
            } else {
                None
            },
            cam: Cam::new(CAMERA_BUF_X, CAMERA_BUF_Y),
        }
    }

    fn on_draw(&mut self,
               args: &RenderArgs,
               mut w: &mut PistonWindow,
               e: &Event,
               tileset: &Tileset,
               mut level: &mut Level) {
        let player_one = &self.player_one.creature;
        let player_two = &self.player_two;
        let coord1 = self.player_one.coord.clone();
        let mut coord2 = coord1.clone();
        if let Some(ref p2) = *player_two {
            coord2 = p2.coord.clone();
        }
        self.cam.calc_coordinates(coord1, coord2);
        let range = self.cam.get_range();
        w.draw_2d(e, |c, gl| {
            // Clear the screen.
            clear(BLACK, gl);
            let center_p1 = c.transform.trans((self.player_one.coord.get_x() * 65) as f64,
                                              (self.player_one.coord.get_y() * 65) as f64);
            let center_lv = c.transform.trans(0.0, 0.0);

            //render_level(&tileset, gl, center_lv, &mut level);
            for i in range.x_min..range.x_max {
                for j in range.y_min..range.y_max {
                    let tile = match tileset.get_texture(level.get_data()[i as usize][j as usize].get_id()) {
                    Some(x) => x,
                    None => panic!("No texture found."),
                    };
                    // DEBUG
                    //println!("{} {}", i, j);
                    render_tile(&tile, gl, center_lv,  j as u32 * TILE_HEIGHT,
                            i as u32 * TILE_WIDTH,
                            i as u32,
                            j as u32);
                }
            }
            player_one.render(gl, center_p1);
            if let Some(ref x) = *player_two {
                x.creature.render(gl, center_p1);
            }
        });
    }

    fn on_update(&mut self,
                 args: &UpdateArgs,) {

        self.player_one.on_update(args);
        if let Some(ref mut x) = self.player_two {

            x.on_update(args);
        }

    }

    fn on_input(&mut self, inp: Button, pressed: bool) {

        match inp {
            Button::Keyboard(Key::Up) => {
                if pressed {
                    self.player_one.last = LastKey::Up;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Down) => {
                if pressed {
                    self.player_one.last = LastKey::Down;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Left) => {
                if pressed {
                    self.player_one.last = LastKey::Left;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Right) => {
                if pressed {
                    self.player_one.last = LastKey::Right;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::W) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Up;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::S) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Down;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::A) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Left;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::D) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Right;
                    }
                    x.pressed = pressed;
                }
            }
            _ => {}

        }
    }
    fn on_load(&mut self, mut w: &mut PistonWindow) {
        let mut player_one = &mut self.player_one;
        App::load_sprite(w, &mut player_one, SPRITE_P_1);
        if let Some(ref mut x) = self.player_two {
            App::load_sprite(w, x, SPRITE_P_2);
        }

    }
    fn load_sprite(mut w: &mut PistonWindow, player: &mut Player, file: &str) {
        let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
        let tank_sprite = assets.join(file);
        let tank_sprite2 = Texture::from_path(&mut w.factory,
                                              &tank_sprite,
                                              Flip::None,
                                              &TextureSettings::new());
        match tank_sprite2 {
            Err(_) => {
                println!("Empty");
            }
            Ok(x) => {
                player.creature.set_sprite(x);
            }
        }

    }
}

fn main() {
    // Create an Glutin window.
    let mut window: PistonWindow = WindowSettings::new("spinning-square",
                                                       [WIDTH as u32, HEIGHT as u32])
        .exit_on_esc(true)
        //.fullscreen(true)
        .build()
        .unwrap();

    // Create a new game and run it.

    let mut app = App::new(TWO_PLAYER);
    app.on_load(&mut window);

    let mut events = window.events();

    let folder = match find_folder::Search::Kids(1).for_folder("tiles") {
        Ok(res) => res.join("tileset-pokemon_dawn.png"),
        Err(_) => panic!("Folder 'tiles' not found!"),
    };

    let file_path = match folder.to_str() {
        Some(res) => res,
        None => panic!("Tileset not found!"),
    };

    let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
        Ok(res) => res.join("level1.lvl"),
        Err(_) => panic!("Folder 'src' not found!"),
    };

    let level_path = match folder_level.to_str() {
        Some(res) => res,
        None => panic!("Level not found!"),
    };

    let tileset = io::read_tileset(file_path, &mut window);

    let mut level = io::read_level(level_path);

    let mut start = PreciseTime::now();
    app.cam.set_borders((level.get_x() as u64, level.get_y()as u64));

    while let Some(e) = events.next(&mut window) {
        let now = start.to(PreciseTime::now()).num_milliseconds();
        //println!("{}", now);

        if let Some(r) = e.render_args() {
            app.on_draw(&r, &mut window, &e, &tileset, &mut level);
        }
        if let Some(i) = e.release_args() {
            app.on_input(i, false);
        }
        if let Some(i) = e.press_args() {
            app.on_input(i, true);
        }
        if now > 500 {
            if let Some(u) = e.update_args() {
                app.on_update(&u);
                start = PreciseTime::now();
            }
        }

    }

}

//UTIL//////////////////////////////

fn border_add(add1: f64, add2: f64, width: bool) -> f64 {
    let border = (if width { WIDTH } else { HEIGHT }) as f64;
    let sum = add1 + add2;
    if sum < 0.0 {
        0.0
    } else if sum > border {
        border
    } else {
        sum
    }
}
<|endoftext|>


<commit_before>//! Command line utility for querying and working with Iridium SBD messages.

extern crate docopt;
extern crate rustc_serialize;
extern crate sbd;

use docopt::Docopt;

use sbd::filesystem::Storage;

const USAGE: &'static str = "
Iridium Short Burst Data (SBD) message utility.

Usage:
    sbd list <directory>
    sbd (-h | --help)
    sbd --version

Options:
    -h --help   Show this information
    --version   Show version
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_list: bool,
    arg_directory: String,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| Ok(d.version(Some(env!("CARGO_PKG_VERSION").to_string()))))
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    if args.cmd_list {
        for entry in &Storage::new(args.arg_directory) {
            println!("{}", entry.path_buf.to_str().unwrap());
        }
    }
}
<commit_msg>Add a read command to the binary<commit_after>//! Command line utility for querying and working with Iridium SBD messages.

extern crate docopt;
extern crate rustc_serialize;
extern crate sbd;

use std::str;

use docopt::Docopt;

use sbd::filesystem::Storage;
use sbd::message::Message;

const USAGE: &'static str = "
Iridium Short Burst Data (SBD) message utility.

Usage:
    sbd list <directory>
    sbd read <file>
    sbd (-h | --help)
    sbd --version

Options:
    -h --help   Show this information
    --version   Show version
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_list: bool,
    cmd_read: bool,
    arg_directory: String,
    arg_file: String,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| Ok(d.version(Some(env!("CARGO_PKG_VERSION").to_string()))))
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    if args.cmd_list {
        for entry in &Storage::new(args.arg_directory) {
            println!("{}", entry.path_buf.to_str().unwrap());
        }
    }
    if args.cmd_read {
        match Message::from_path(args.arg_file) {
            Ok(message) => {
                println!("{}", str::from_utf8(message.payload_ref()).unwrap());
            }
            Err(err) => println!("ERROR: {:?}", err),
        }
    }
}
<|endoftext|>


<commit_before>use crate::*;

/// A simple map that can be used to store metadata
/// for the pagecache tenant.
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct Meta {
    pub(crate) inner: BTreeMap<IVec, PageId>,
}

impl Meta {
    /// Retrieve the `PageId` associated with an identifier
    pub fn get_root(&self, table: &[u8]) -> Option<PageId> {
        self.inner.get(table).cloned()
    }

    /// Set the `PageId` associated with an identifier
    pub fn set_root(&mut self, name: IVec, pid: PageId) -> Option<PageId> {
        self.inner.insert(name, pid)
    }

    /// Remove the page mapping for a given identifier
    pub fn del_root(&mut self, name: &[u8]) -> Option<PageId> {
        self.inner.remove(name)
    }

    /// Return the current rooted tenants in Meta
    pub fn tenants(&self) -> BTreeMap<IVec, PageId> {
        self.inner.clone()
    }

    pub(crate) fn size_in_bytes(&self) -> u64 {
        self.inner
            .iter()
            .map(|(k, _pid)| {
                k.len() as u64 + std::mem::size_of::<PageId>() as u64
            })
            .sum()
    }
}

/// Open or create a new disk-backed Tree with its own keyspace,
/// accessible from the `Db` via the provided identifier.
pub(crate) fn open_tree<V>(
    context: &Context,
    raw_name: V,
    guard: &Guard,
) -> Result<Tree>
where
    V: Into<IVec>,
{
    let name = raw_name.into();

    // we loop because creating this Tree may race with
    // concurrent attempts to open the same one.
    loop {
        match context.pagecache.meta_pid_for_name(&name, guard) {
            Ok(root_id) => {
                return Ok(Tree(Arc::new(TreeInner {
                    tree_id: IVec::from(name),
                    context: context.clone(),
                    subscriptions: Subscriptions::default(),
                    root: AtomicU64::new(root_id),
                    concurrency_control: RwLock::new(()),
                    merge_operator: RwLock::new(None),
                })));
            }
            Err(Error::CollectionNotFound(_)) => {}
            Err(other) => return Err(other),
        }

        // set up empty leaf
        let leaf = Node { data: Data::Leaf(vec![]), ..Node::default() };
        let (leaf_id, leaf_ptr) = context.pagecache.allocate(leaf, guard)?;

        trace!(
            "allocated pid {} for leaf in new_tree for namespace {:?}",
            leaf_id,
            name
        );

        // set up root index

        // vec![0] represents a prefix-encoded empty prefix
        let root_index_vec = vec![(prefix::empty().into(), leaf_id)];
        let root =
            Node { data: Data::Index(root_index_vec), ..Node::default() };
        let (root_id, root_ptr) = context.pagecache.allocate(root, guard)?;

        debug!("allocated pid {} for root of new_tree {:?}", root_id, name);

        let res = context.pagecache.cas_root_in_meta(
            &name,
            None,
            Some(root_id),
            guard,
        )?;

        if res.is_err() {
            // clean up the tree we just created if we couldn't
            // install it.
            let _ = context
                .pagecache
                .free(root_id, root_ptr, guard)?
                .expect("could not free allocated page");
            let _ = context
                .pagecache
                .free(leaf_id, leaf_ptr, guard)?
                .expect("could not free allocated page");
            continue;
        }

        return Ok(Tree(Arc::new(TreeInner {
            tree_id: name,
            subscriptions: Subscriptions::default(),
            context: context.clone(),
            root: AtomicU64::new(root_id),
            concurrency_control: RwLock::new(()),
            merge_operator: RwLock::new(None),
        })));
    }
}
<commit_msg>Address clippy feedback<commit_after>use crate::*;

/// A simple map that can be used to store metadata
/// for the pagecache tenant.
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct Meta {
    pub(crate) inner: BTreeMap<IVec, PageId>,
}

impl Meta {
    /// Retrieve the `PageId` associated with an identifier
    pub fn get_root(&self, table: &[u8]) -> Option<PageId> {
        self.inner.get(table).cloned()
    }

    /// Set the `PageId` associated with an identifier
    pub fn set_root(&mut self, name: IVec, pid: PageId) -> Option<PageId> {
        self.inner.insert(name, pid)
    }

    /// Remove the page mapping for a given identifier
    pub fn del_root(&mut self, name: &[u8]) -> Option<PageId> {
        self.inner.remove(name)
    }

    /// Return the current rooted tenants in Meta
    pub fn tenants(&self) -> BTreeMap<IVec, PageId> {
        self.inner.clone()
    }

    pub(crate) fn size_in_bytes(&self) -> u64 {
        self.inner
            .iter()
            .map(|(k, _pid)| {
                k.len() as u64 + std::mem::size_of::<PageId>() as u64
            })
            .sum()
    }
}

/// Open or create a new disk-backed Tree with its own keyspace,
/// accessible from the `Db` via the provided identifier.
pub(crate) fn open_tree<V>(
    context: &Context,
    raw_name: V,
    guard: &Guard,
) -> Result<Tree>
where
    V: Into<IVec>,
{
    let name = raw_name.into();

    // we loop because creating this Tree may race with
    // concurrent attempts to open the same one.
    loop {
        match context.pagecache.meta_pid_for_name(&name, guard) {
            Ok(root_id) => {
                return Ok(Tree(Arc::new(TreeInner {
                    tree_id: name,
                    context: context.clone(),
                    subscriptions: Subscriptions::default(),
                    root: AtomicU64::new(root_id),
                    concurrency_control: RwLock::new(()),
                    merge_operator: RwLock::new(None),
                })));
            }
            Err(Error::CollectionNotFound(_)) => {}
            Err(other) => return Err(other),
        }

        // set up empty leaf
        let leaf = Node { data: Data::Leaf(vec![]), ..Node::default() };
        let (leaf_id, leaf_ptr) = context.pagecache.allocate(leaf, guard)?;

        trace!(
            "allocated pid {} for leaf in new_tree for namespace {:?}",
            leaf_id,
            name
        );

        // set up root index

        // vec![0] represents a prefix-encoded empty prefix
        let root_index_vec = vec![(prefix::empty().into(), leaf_id)];
        let root =
            Node { data: Data::Index(root_index_vec), ..Node::default() };
        let (root_id, root_ptr) = context.pagecache.allocate(root, guard)?;

        debug!("allocated pid {} for root of new_tree {:?}", root_id, name);

        let res = context.pagecache.cas_root_in_meta(
            &name,
            None,
            Some(root_id),
            guard,
        )?;

        if res.is_err() {
            // clean up the tree we just created if we couldn't
            // install it.
            let _ = context
                .pagecache
                .free(root_id, root_ptr, guard)?
                .expect("could not free allocated page");
            let _ = context
                .pagecache
                .free(leaf_id, leaf_ptr, guard)?
                .expect("could not free allocated page");
            continue;
        }

        return Ok(Tree(Arc::new(TreeInner {
            tree_id: name,
            subscriptions: Subscriptions::default(),
            context: context.clone(),
            root: AtomicU64::new(root_id),
            concurrency_control: RwLock::new(()),
            merge_operator: RwLock::new(None),
        })));
    }
}
<|endoftext|>


<commit_before>use config::Config;
use error::Result;
use error::Error;
use ip::IpAddr;
use hyper::Client;
use hyper::header::Connection;
use std::io;
use std::io::prelude::*;
use std::result::Result as StdResult;
use std::str::FromStr;
use regex::Regex;

#[derive(Debug)]
pub enum IpProvider {
    Stdin,
    SfrLaBoxFibre,
}

impl FromStr for IpProvider {
    type Err = String;

    fn from_str(s: &str) -> StdResult<IpProvider, String> {
        match s {
            "-" => Ok(IpProvider::Stdin),
            "sfrlaboxfibre" => Ok(IpProvider::SfrLaBoxFibre),
            value => Err(format!("Unknown value for IP provider: {}", value).to_owned()),
        }
    }
}

pub trait IpAddressProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr>;
}

impl IpAddressProvider {
    pub fn from_config(config: &Config) -> Box<IpAddressProvider + 'static>  {
        match config.ip_provider {
            IpProvider::Stdin => Box::new(StdinIpProvider),
            IpProvider::SfrLaBoxFibre => Box::new(HttpIpProvider),
        }
    }
}

pub struct StdinIpProvider;

impl IpAddressProvider for StdinIpProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let mut input = String::new();

        try!(io::stdin().read_line(&mut input));

        trace!("Read stdin: {}", input);

        let ip_addr = try!(IpAddr::from_str(input.trim()));
        Ok(ip_addr)
    }
}

pub struct HttpIpProvider;

impl IpAddressProvider for HttpIpProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let client = Client::new();

        let mut res = try!(client.get("http://192.168.0.1/")
            .header(Connection::close())
            .send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        trace!("HTTP Response: {}", body);

        let regex = try!(Regex::new(r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"));

        regex.captures(&*body)
            .and_then(|caps| caps.at(1))
            // Convert Option to Result
            .ok_or(Error::IpNotFound)
            .and_then(|val| IpAddr::from_str(val).map_err(|e| {
                error!("IP parse error: {}", e);
                Error::IpNotFound
            }))
    }
}
<commit_msg>Extract URL of HTTP provider into constants<commit_after>use config::Config;
use error::Result;
use error::Error;
use ip::IpAddr;
use hyper::Client;
use hyper::header::Connection;
use std::io;
use std::io::prelude::*;
use std::result::Result as StdResult;
use std::str::FromStr;
use regex::Regex;

// All HTTP IP providers URL
static URL_SFR_LABOX_FIBRE: &'static str = "http://192.168.0.1/";

#[derive(Debug)]
pub enum IpProvider {
    Stdin,
    SfrLaBoxFibre,
}

impl FromStr for IpProvider {
    type Err = String;

    fn from_str(s: &str) -> StdResult<IpProvider, String> {
        match s {
            "-" => Ok(IpProvider::Stdin),
            "sfrlaboxfibre" => Ok(IpProvider::SfrLaBoxFibre),
            value => Err(format!("Unknown value for IP provider: {}", value).to_owned()),
        }
    }
}

pub trait IpAddressProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr>;
}

impl IpAddressProvider {
    pub fn from_config(config: &Config) -> Box<IpAddressProvider + 'static>  {
        match config.ip_provider {
            IpProvider::Stdin => Box::new(StdinIpProvider),
            IpProvider::SfrLaBoxFibre => Box::new(HttpIpProvider::new(URL_SFR_LABOX_FIBRE)),
        }
    }
}

pub struct StdinIpProvider;

impl IpAddressProvider for StdinIpProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let mut input = String::new();

        try!(io::stdin().read_line(&mut input));

        trace!("Read stdin: {}", input);

        let ip_addr = try!(IpAddr::from_str(input.trim()));
        Ok(ip_addr)
    }
}

pub struct HttpIpProvider<'a> {
    url: &'a str,
}

impl<'a> HttpIpProvider<'a> {
    fn new(url: &'a str) -> HttpIpProvider {
        HttpIpProvider {
            url: url,
        }
    }
}

impl<'a> IpAddressProvider for HttpIpProvider<'a> {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let client = Client::new();

        let mut res = try!(client.get(self.url)
            .header(Connection::close())
            .send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        trace!("HTTP Response: {}", body);

        let regex = try!(Regex::new(r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"));

        regex.captures(&*body)
            .and_then(|caps| caps.at(1))
            // Convert Option to Result
            .ok_or(Error::IpNotFound)
            .and_then(|val| IpAddr::from_str(val).map_err(|e| {
                error!("IP parse error: {}", e);
                Error::IpNotFound
            }))
    }
}
<|endoftext|>


<commit_before>use std::task::TaskBuilder;
use std::io::{TcpListener, TcpStream, Acceptor, Listener};
use std::io::net::tcp::TcpAcceptor;
use std::collections::HashMap;

use uuid::Uuid;
use addr::Addr;
use result::{GossipResult, GossipError, NotListening};
use broadcast::Broadcast;
use incoming::Incoming;

/// A dedicated Rust task to manage a single `TcpStream`. Each
/// stream is then associated to a given peer (although the peer
/// isn't always set right away).
///
/// This task then has channels to communicate with the main
/// AcceptorTask which can communicate with other StreamTasks.
struct StreamTask {
    peer: Option<Peer>,
    stream: TcpStream
}

impl StreamTask {
    pub fn new(stream: TcpStream) -> StreamTask {
        StreamTask {
            peer: None,
            stream: stream
        }
    }

    pub fn incoming(&mut self) {

    }
}

/// A dedicated task to handle the incoming connections
/// over a tcp socket (called streams). This task does
/// not need to communicate with the streams themselves, that's
/// done at another task that handles the core logic of the
/// protocol.
struct AcceptorTask {
    acceptor: TcpAcceptor,
    server_tx: Sender<Broadcast>,
    tx: Sender<Broadcast>,
    rx: Receiver<Broadcast>
}

impl AcceptorTask {
    pub fn new(host: &str, port: u16, server_tx: Sender<Broadcast>, inter_tx: Sender<Sender<Broadcast>>) -> AcceptorTask {
        let listener = TcpListener::bind(host, port).unwrap();
        let (tx, rx) = channel();

        inter_tx.send(tx.clone());

        AcceptorTask {
            acceptor: listener.listen().unwrap(),
            server_tx: server_tx,
            tx: tx,
            rx: rx
        }
    }

    pub fn run(&mut self) {
        for stream in self.acceptor.incoming() {
            match stream {
                Ok(stream) => spawn(proc() {
                    StreamTask::new(stream).incoming();
                }),
                Err(e) => println!("Error: {}", e)
            }
        }
    }
}

struct ServerTask {
    streams: HashMap<Peer, Sender<Broadcast>>,
    acceptor_tx: Sender<Broadcast>,
    tx: Sender<Broadcast>,
    rx: Receiver<Broadcast>
}

impl ServerTask {
    pub fn new(host: String, port: u16) -> ServerTask {
        // Local channels that deal with broadcasts.
        let (tx, rx) = channel();

        // Intermediate channels for the acceptor task.
        // We'll use this to retrieve the sender of the
        // acceptor task.
        let (acceptor_tx, acceptor_rx) = channel();

        let server_tx = tx.clone();
        spawn(proc() {
            AcceptorTask::new(host.as_slice(), port, server_tx, acceptor_tx).run();
        });

        ServerTask {
            streams: HashMap::new(),
            acceptor_tx: acceptor_rx.recv(),
            tx: tx,
            rx: rx
        }
    }

    pub fn run(&mut self) {

    }
}

/// A peer describes a member within the cluster/network that
/// is not the current one.
#[deriving(Show, PartialEq, Hash, Eq)]
pub struct Peer {
    id: Uuid,
    addr: Addr
}

/// A `Node` is a single member within the gossip protocol. Nodes that
/// join together is called a cluster. This forms the distributed system
/// in which the gossip protocol runs within.
///
/// Each Node is an equal member in the cluster. That means there isn't a
/// single leader. This has a significant trade-off and one must understand
/// it before being able to use the system correctly.
///
/// Node: Handle the state.
/// Incoming: Handle incoming connections and broadcasts.
pub struct Node {
    /// Each node generates their own unique Uuid (v4) to uniquely
    /// identify each other within the cluster. Instead of saying
    /// "I'm node A", you would say "I'm node 123e4567-e89b-12d3-a456-426655440000".
    id: Uuid,

    /// A set of other members within the cluster. This forms the basic
    /// information about each Node. This doesn't, however, contain connection
    /// information and what not.
    members: Vec<Peer>,
    incoming_tx: Option<Sender<Broadcast>>,
    tx: Sender<(Peer, Broadcast)>,
    rx: Receiver<(Peer, Broadcast)>
}

impl Node {
    /// Usage:
    ///
    /// ```rust
    /// use gossip::Node;
    /// let mut node = Node::new();
    /// ```
    pub fn new() -> Node {
        let (tx, rx) = channel();

        Node {
            id: Uuid::new_v4(),
            members: Vec::new(),
            incoming_tx: None,
            tx: tx,
            rx: rx
        }
    }

    /// Initialize the Node to listen on the specified address/port
    /// combination. This will bootup the appropriate tasks to allow
    /// incoming connections and broadcasts.
    #[unimplemented]
    pub fn listen(&mut self, host: &str, port: u16) -> GossipResult<()> {
        let host = host.to_string();

        spawn(proc() {
            ServerTask::new(host, port).run();
        });

        Ok(())
    }

    /// Given a peer node, join it's existing cluster. Each node technically
    /// creates their own cluster automatically. Joining multiple nodes together
    /// is an explicit process. The peer node doesn't need to be the same one,
    /// but it's not a bad idea.
    #[unimplemented]
    pub fn join(&mut self, host: &str, port: u16) -> GossipResult<()> {
        Ok(())
    }

    /// Shutdown all the running tasks that are listening to new broadcasts
    /// and incoming connections. This will send one last broadcast
    /// to the current cluster notifying all other nodes of the shutdown.
    ///
    /// Afterwhich tasks will shutdown and the node will be terminated.
    #[unimplemented]
    pub fn shutdown(&mut self) {}

    /// Create a new `Incoming` iterator that iterates over newly received
    /// broadcasts that the user can handle.
    ///
    /// Usage:
    ///
    /// ```notrust
    /// use gossip::Node;
    /// spawn(proc() {
    ///     let mut node = Node::new();
    ///
    ///     node.listen("localhost", 4888).unwrap();
    ///
    ///     for (broadcast, mut res) in node.incoming() {
    ///         println!("Broadcast ...");
    ///         // ...
    ///     }
    /// });
    /// ```
    pub fn incoming(&mut self) -> Incoming {
        let (tx, rx) = channel();
        let incoming = Incoming::new(self.tx.clone(), tx);

        self.incoming_tx = Some(rx.recv());

        incoming
    }
}

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

    #[test]
    fn empty_member_set() {
        let mut node = Node::new();
        assert_eq!(node.members.len(), 0);
    }

    #[test]
    fn bind_listening() {
        let mut node = Node::new();
    }
}
<commit_msg>Fixed formatting<commit_after>use std::task::TaskBuilder;
use std::io::{TcpListener, TcpStream, Acceptor, Listener};
use std::io::net::tcp::TcpAcceptor;
use std::collections::HashMap;

use uuid::Uuid;
use addr::Addr;
use result::{GossipResult, GossipError, NotListening};
use broadcast::Broadcast;
use incoming::Incoming;

/// A dedicated Rust task to manage a single `TcpStream`. Each
/// stream is then associated to a given peer (although the peer
/// isn't always set right away).
///
/// This task then has channels to communicate with the main
/// AcceptorTask which can communicate with other StreamTasks.
struct StreamTask {
    peer: Option<Peer>,
    stream: TcpStream
}

impl StreamTask {
    pub fn new(stream: TcpStream) -> StreamTask {
        StreamTask {
            peer: None,
            stream: stream
        }
    }

    pub fn incoming(&mut self) {

    }
}

/// A dedicated task to handle the incoming connections
/// over a tcp socket (called streams). This task does
/// not need to communicate with the streams themselves, that's
/// done at another task that handles the core logic of the
/// protocol.
struct AcceptorTask {
    acceptor: TcpAcceptor,
    server_tx: Sender<Broadcast>,
    tx: Sender<Broadcast>,
    rx: Receiver<Broadcast>
}

impl AcceptorTask {
    pub fn new(host: &str, port: u16, server_tx: Sender<Broadcast>,
               inter_tx: Sender<Sender<Broadcast>>) -> AcceptorTask {
        let listener = TcpListener::bind(host, port).unwrap();
        let (tx, rx) = channel();

        inter_tx.send(tx.clone());

        AcceptorTask {
            acceptor: listener.listen().unwrap(),
            server_tx: server_tx,
            tx: tx,
            rx: rx
        }
    }

    pub fn run(&mut self) {
        for stream in self.acceptor.incoming() {
            match stream {
                Ok(stream) => spawn(proc() {
                    StreamTask::new(stream).incoming();
                }),
                Err(e) => println!("Error: {}", e)
            }
        }
    }
}

struct ServerTask {
    streams: HashMap<Peer, Sender<Broadcast>>,
    acceptor_tx: Sender<Broadcast>,
    tx: Sender<Broadcast>,
    rx: Receiver<Broadcast>
}

impl ServerTask {
    pub fn new(host: String, port: u16) -> ServerTask {
        // Local channels that deal with broadcasts.
        let (tx, rx) = channel();

        // Intermediate channels for the acceptor task.
        // We'll use this to retrieve the sender of the
        // acceptor task.
        let (acceptor_tx, acceptor_rx) = channel();

        let server_tx = tx.clone();
        spawn(proc() {
            AcceptorTask::new(host.as_slice(), port, server_tx, acceptor_tx).run();
        });

        ServerTask {
            streams: HashMap::new(),
            acceptor_tx: acceptor_rx.recv(),
            tx: tx,
            rx: rx
        }
    }

    pub fn run(&mut self) {

    }
}

/// A peer describes a member within the cluster/network that
/// is not the current one.
#[deriving(Show, PartialEq, Hash, Eq)]
pub struct Peer {
    id: Uuid,
    addr: Addr
}

/// A `Node` is a single member within the gossip protocol. Nodes that
/// join together is called a cluster. This forms the distributed system
/// in which the gossip protocol runs within.
///
/// Each Node is an equal member in the cluster. That means there isn't a
/// single leader. This has a significant trade-off and one must understand
/// it before being able to use the system correctly.
///
/// Node: Handle the state.
/// Incoming: Handle incoming connections and broadcasts.
pub struct Node {
    /// Each node generates their own unique Uuid (v4) to uniquely
    /// identify each other within the cluster. Instead of saying
    /// "I'm node A", you would say "I'm node 123e4567-e89b-12d3-a456-426655440000".
    id: Uuid,

    /// A set of other members within the cluster. This forms the basic
    /// information about each Node. This doesn't, however, contain connection
    /// information and what not.
    members: Vec<Peer>,
    incoming_tx: Option<Sender<Broadcast>>,
    tx: Sender<(Peer, Broadcast)>,
    rx: Receiver<(Peer, Broadcast)>
}

impl Node {
    /// Usage:
    ///
    /// ```rust
    /// use gossip::Node;
    /// let mut node = Node::new();
    /// ```
    pub fn new() -> Node {
        let (tx, rx) = channel();

        Node {
            id: Uuid::new_v4(),
            members: Vec::new(),
            incoming_tx: None,
            tx: tx,
            rx: rx
        }
    }

    /// Initialize the Node to listen on the specified address/port
    /// combination. This will bootup the appropriate tasks to allow
    /// incoming connections and broadcasts.
    #[unimplemented]
    pub fn listen(&mut self, host: &str, port: u16) -> GossipResult<()> {
        let host = host.to_string();

        spawn(proc() {
            ServerTask::new(host, port).run();
        });

        Ok(())
    }

    /// Given a peer node, join it's existing cluster. Each node technically
    /// creates their own cluster automatically. Joining multiple nodes together
    /// is an explicit process. The peer node doesn't need to be the same one,
    /// but it's not a bad idea.
    #[unimplemented]
    pub fn join(&mut self, host: &str, port: u16) -> GossipResult<()> {
        Ok(())
    }

    /// Shutdown all the running tasks that are listening to new broadcasts
    /// and incoming connections. This will send one last broadcast
    /// to the current cluster notifying all other nodes of the shutdown.
    ///
    /// Afterwhich tasks will shutdown and the node will be terminated.
    #[unimplemented]
    pub fn shutdown(&mut self) {}

    /// Create a new `Incoming` iterator that iterates over newly received
    /// broadcasts that the user can handle.
    ///
    /// Usage:
    ///
    /// ```notrust
    /// use gossip::Node;
    /// spawn(proc() {
    ///     let mut node = Node::new();
    ///
    ///     node.listen("localhost", 4888).unwrap();
    ///
    ///     for (broadcast, mut res) in node.incoming() {
    ///         println!("Broadcast ...");
    ///         // ...
    ///     }
    /// });
    /// ```
    pub fn incoming(&mut self) -> Incoming {
        let (tx, rx) = channel();
        let incoming = Incoming::new(self.tx.clone(), tx);

        self.incoming_tx = Some(rx.recv());

        incoming
    }
}

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

    #[test]
    fn empty_member_set() {
        let mut node = Node::new();
        assert_eq!(node.members.len(), 0);
    }

    #[test]
    fn bind_listening() {
        let mut node = Node::new();
    }
}
<|endoftext|>


<commit_before>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    Var(usize),
    Abs(Box<Term>),
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Applies `self` to another term with substitution and variable update, consuming them
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::apply;
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(rhs), Ok(result));
    /// ```
    pub fn apply(mut self, rhs: Term) -> Result<Term, Error> {
        _apply(&mut self, rhs, 0);

        Ok(try!(self.unabs()))
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(abs(abs(Var(1)))));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (mut lhs, rhs) = try!(self.unapp());

        _apply(&mut lhs, rhs, 0);

        Ok(try!(lhs.unabs()))
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

/// Applies two terms with substitution and variable update, consuming them in the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    Ok(try!(lhs.unabs()))
}

fn _apply(lhs: &mut Term, rhs: Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs; // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1) // update free variables' indices from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs.clone(), depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth);
        }
    }
}

fn update_free_variables(term: &mut Term, depth: usize) {
    match *term {
        Var(i) => if i > depth {
            *term = Var(i + depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), depth)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), depth);
        }
    }
}

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(0, self))
    }
}

fn show_precedence(context_precedence: usize, term: &Term) -> String {
    match *term {
        Var(i) => format!("{:X}", i), // max. index = 15
        Abs(ref t) => {
            let ret = format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t);
            parenthesize_if(context_precedence > 1, &ret).into()
        },
        App(ref t1, ref t2) => {
            let ret = format!("{}{}", show_precedence(2, t1), show_precedence(3, t2));
            parenthesize_if(context_precedence == 3, &ret).into()
        }
    }
}

fn parenthesize_if(condition: bool, input: &str) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

#[cfg(test)]
mod test {
    use arithmetic::{zero, succ, pred};
    use combinators::i;
    use parser::parse;
    use term::{apply, abs};
    use term::Term::Var;

    #[test]
    fn applying() {
        let lhs    = parse(&"λλ42(λ13)").unwrap();
        let rhs    = parse(&"λ51").unwrap();
        let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
        assert_eq!(apply(lhs, rhs), Ok(result));

        assert_eq!(i().app(zero()).apply().unwrap(), abs(abs(Var(1))));
    }

    #[test]
    fn displaying_terms() {
        assert_eq!(&format!("{}", zero()), "λλ1");
        assert_eq!(&format!("{}", succ()), "λλλ2(321)");
        assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
    }
}
<commit_msg>Fix one test<commit_after>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    Var(usize),
    Abs(Box<Term>),
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Applies `self` to another term with substitution and variable update, consuming them
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::apply;
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(rhs), Ok(result));
    /// ```
    pub fn apply(mut self, rhs: Term) -> Result<Term, Error> {
        _apply(&mut self, rhs, 0);

        Ok(try!(self.unabs()))
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(abs(abs(Var(1)))));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (mut lhs, rhs) = try!(self.unapp());

        _apply(&mut lhs, rhs, 0);

        Ok(try!(lhs.unabs()))
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

/// Applies two terms with substitution and variable update, consuming them in the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    Ok(try!(lhs.unabs()))
}

fn _apply(lhs: &mut Term, rhs: Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs; // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1) // update free variables' indices from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs.clone(), depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth);
        }
    }
}

fn update_free_variables(term: &mut Term, depth: usize) {
    match *term {
        Var(i) => if i > depth {
            *term = Var(i + depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), depth)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), depth);
        }
    }
}

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(0, self))
    }
}

fn show_precedence(context_precedence: usize, term: &Term) -> String {
    match *term {
        Var(i) => format!("{:X}", i), // max. index = 15
        Abs(ref t) => {
            let ret = format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t);
            parenthesize_if(context_precedence > 1, &ret).into()
        },
        App(ref t1, ref t2) => {
            let ret = format!("{}{}", show_precedence(2, t1), show_precedence(3, t2));
            parenthesize_if(context_precedence == 3, &ret).into()
        }
    }
}

fn parenthesize_if(condition: bool, input: &str) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

#[cfg(test)]
mod test {
    use arithmetic::{zero, succ, pred};
    use combinators::i;
    use parser::parse;
    use term::{apply, abs};
    use term::Term::Var;

    #[test]
    fn applying() {
        let lhs    = parse(&"λλ42(λ13)").unwrap();
        let rhs    = parse(&"λ51").unwrap();
        let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
        assert_eq!(apply(lhs, rhs), Ok(result));

        assert_eq!(i().app(zero()).eval().unwrap(), abs(abs(Var(1))));
    }

    #[test]
    fn displaying_terms() {
        assert_eq!(&format!("{}", zero()), "λλ1");
        assert_eq!(&format!("{}", succ()), "λλλ2(321)");
        assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
    }
}
<|endoftext|>


<commit_before>extern crate libc;
use std::os::raw::*;

use super::{Width, Height};

const TIOCGWINSZ: c_int = 0x00005413;

#[derive(Debug)]
struct WinSize {
    ws_row: c_ushort,
    ws_col: c_ushort,
    ws_xpixel: c_ushort,
    ws_ypixel: c_ushort
}

/// Returns the size of the terminal, if available.
///
/// If STDIN is not a tty, returns `None`
pub fn terminal_size() -> Option<(Width, Height)> {
    use self::libc::{isatty, STDIN_FILENO};
    use self::libc::funcs::bsd44::ioctl;
    let is_tty: bool = unsafe{isatty(STDIN_FILENO) == 1};

    if !is_tty { return None; }

    let (rows, cols) = unsafe {
        let mut winsize = WinSize{ws_row: 0, ws_col: 0, ws_xpixel: 0, ws_ypixel: 0};
        ioctl(STDIN_FILENO, TIOCGWINSZ, &mut winsize);
        println!("{:?}", winsize);
        let rows = if winsize.ws_row > 0 { winsize.ws_row } else { 0 };
        let cols = if winsize.ws_col > 0 { winsize.ws_col } else { 0 };
        (rows as u16, cols as u16)
    };

    if rows > 0 && cols > 0 {
        Some((Width(cols), Height(rows)))
    } else {
        None
    }
}
<commit_msg>Add test on linux to compare with the output of stty<commit_after>extern crate libc;
use std::os::raw::*;

use super::{Width, Height};

const TIOCGWINSZ: c_int = 0x00005413;

#[derive(Debug)]
struct WinSize {
    ws_row: c_ushort,
    ws_col: c_ushort,
    ws_xpixel: c_ushort,
    ws_ypixel: c_ushort
}

/// Returns the size of the terminal, if available.
///
/// If STDIN is not a tty, returns `None`
pub fn terminal_size() -> Option<(Width, Height)> {
    use self::libc::{isatty, STDIN_FILENO};
    use self::libc::funcs::bsd44::ioctl;
    let is_tty: bool = unsafe{isatty(STDIN_FILENO) == 1};

    if !is_tty { return None; }

    let (rows, cols) = unsafe {
        let mut winsize = WinSize{ws_row: 0, ws_col: 0, ws_xpixel: 0, ws_ypixel: 0};
        ioctl(STDIN_FILENO, TIOCGWINSZ, &mut winsize);
        println!("{:?}", winsize);
        let rows = if winsize.ws_row > 0 { winsize.ws_row } else { 0 };
        let cols = if winsize.ws_col > 0 { winsize.ws_col } else { 0 };
        (rows as u16, cols as u16)
    };

    if rows > 0 && cols > 0 {
        Some((Width(cols), Height(rows)))
    } else {
        None
    }
}

#[test]
/// Compare with the output of `stty size`
fn compare_with_stty() {
    use std::process::Command;
    use std::process::Stdio;

    let output = Command::new("stty").arg("size").arg("-F").arg("/dev/stderr").stderr(Stdio::inherit()).output().unwrap();
    let stdout = String::from_utf8(output.stdout).unwrap();
    assert!(output.status.success());
    // stdout is "rows cols"
    let mut data = stdout.split_whitespace();
    let rows = u16::from_str_radix(data.next().unwrap(), 10).unwrap();
    let cols = u16::from_str_radix(data.next().unwrap(), 10).unwrap();
    println!("{}", stdout);
    println!("{} {}", rows, cols);

    if let Some((Width(w), Height(h))) = terminal_size() {
        assert_eq!(rows, h);
        assert_eq!(cols, w);
    }

}
<|endoftext|>


<commit_before>#[doc = "

Finds crate binaries and loads their metadata

"];

import driver::session;
import session::session;
import syntax::{ast, attr};
import syntax::print::pprust;
import syntax::codemap::span;
import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
import util::{filesearch};
import io::writer_util;

export load_library_crate;
export list_file_metadata;
export note_linkage_attrs;
export crate_name_from_metas;
export metadata_matches;

fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
                      metas: [@ast::meta_item], hash: str)
   -> {ident: str, data: @[u8]} {

    alt find_library_crate(sess, span, metas, hash) {
      some(t) { ret t; }
      none {
        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
      }
    }
}

fn find_library_crate(sess: session::session, span: span,
                      metas: [@ast::meta_item], hash: str)
   -> option<{ident: str, data: @[u8]}> {

    attr::require_unique_names(sess.diagnostic(), metas);
    let metas = metas;

    let nn = default_native_lib_naming(sess, sess.opts.static);
    let x =
        find_library_crate_aux(sess, span, nn,
                               metas, hash, sess.filesearch);
    if x != none || sess.opts.static { ret x; }
    let nn2 = default_native_lib_naming(sess, true);
    ret find_library_crate_aux(sess, span, nn2, metas, hash,
                               sess.filesearch);
}

fn default_native_lib_naming(sess: session::session, static: bool) ->
   {prefix: str, suffix: str} {
    if static { ret {prefix: "lib", suffix: ".rlib"}; }
    alt sess.targ_cfg.os {
      session::os_win32 { ret {prefix: "", suffix: ".dll"}; }
      session::os_macos { ret {prefix: "lib", suffix: ".dylib"}; }
      session::os_linux { ret {prefix: "lib", suffix: ".so"}; }
      session::os_freebsd { ret {prefix: "lib", suffix: ".so"}; }
    }
}

fn find_library_crate_aux(sess: session::session,
                          span: span,
                          nn: {prefix: str, suffix: str},
                          metas: [@ast::meta_item],
                          hash: str,
                          filesearch: filesearch::filesearch) ->
   option<{ident: str, data: @[u8]}> {
    let crate_name = crate_name_from_metas(metas);
    let prefix: str = nn.prefix + crate_name + "-";
    let suffix: str = nn.suffix;

    let mut matches = [];
    filesearch::search(filesearch, { |path|
        #debug("inspecting file %s", path);
        let f: str = path::basename(path);
        if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
            #debug("skipping %s, doesn't look like %s*%s", path, prefix,
                   suffix);
            option::none::<()>
        } else {
            #debug("%s is a candidate", path);
            alt get_metadata_section(sess, path) {
              option::some(cvec) {
                if !crate_matches(cvec, metas, hash) {
                    #debug("skipping %s, metadata doesn't match", path);
                    option::none::<()>
                } else {
                    #debug("found %s with matching metadata", path);
                    matches += [{ident: path, data: cvec}];
                    option::none::<()>
                }
              }
              _ {
                #debug("could not load metadata for %s", path);
                option::none::<()>
              }
            }
        }
    });

    if matches.is_empty() {
        none
    } else if matches.len() == 1u {
        some(matches[0])
    } else {
        sess.span_err(
            span, #fmt("multiple matching crates for `%s`", crate_name));
        sess.note("candidates:");
        for matches.each {|match|
            sess.note(#fmt("path: %s", match.ident));
            let attrs = decoder::get_crate_attributes(match.data);
            note_linkage_attrs(sess, attrs);
        }
        sess.abort_if_errors();
        none
    }
}

fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
    let name_items = attr::find_meta_items_by_name(metas, "name");
    alt vec::last_opt(name_items) {
      some(i) {
        alt attr::get_meta_item_value_str(i) {
          some(n) { n }
          // FIXME: Probably want a warning here since the user
          // is using the wrong type of meta item (#2406)
          _ { fail }
        }
      }
      none { fail "expected to find the crate name" }
    }
}

fn note_linkage_attrs(sess: session::session, attrs: [ast::attribute]) {
    for attr::find_linkage_attrs(attrs).each {|attr|
        sess.note(#fmt("meta: %s", pprust::attr_to_str(attr)));
    }
}

fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
    bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);
    if hash.is_not_empty() {
        let chash = decoder::get_crate_hash(crate_data);
        if chash != hash { ret false; }
    }
    metadata_matches(linkage_metas, metas)
}

fn metadata_matches(extern_metas: [@ast::meta_item],
                    local_metas: [@ast::meta_item]) -> bool {

    #debug("matching %u metadata requirements against %u items",
           vec::len(local_metas), vec::len(extern_metas));

    #debug("crate metadata:");
    for extern_metas.each {|have|
        #debug("  %s", pprust::meta_item_to_str(*have));
    }

    for local_metas.each {|needed|
        #debug("looking for %s", pprust::meta_item_to_str(*needed));
        if !attr::contains(extern_metas, needed) {
            #debug("missing %s", pprust::meta_item_to_str(*needed));
            ret false;
        }
    }
    ret true;
}

fn get_metadata_section(sess: session::session,
                        filename: str) -> option<@[u8]> unsafe {
    let mb = str::as_c_str(filename, {|buf|
        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
                                   });
    if mb as int == 0 { ret option::none::<@[u8]>; }
    let of = alt mk_object_file(mb) {
        option::some(of) { of }
        _ { ret option::none::<@[u8]>; }
    };
    let si = mk_section_iter(of.llof);
    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
        let name_buf = llvm::LLVMGetSectionName(si.llsi);
        let name = unsafe { str::unsafe::from_c_str(name_buf) };
        if str::eq(name, sess.targ_cfg.target_strs.meta_sect_name) {
            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
            let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
            unsafe {
                let cvbuf: *u8 = unsafe::reinterpret_cast(cbuf);
                ret some(@vec::unsafe::from_buf(cvbuf, csz));
            }
        }
        llvm::LLVMMoveToNextSection(si.llsi);
    }
    ret option::none::<@[u8]>;
}

// A diagnostic function for dumping crate metadata to an output stream
fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
    alt get_metadata_section(sess, path) {
      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
      option::none {
        out.write_str("could not find metadata in " + path + ".\n");
      }
    }
}
<commit_msg>rustc: Don't fall back to static libraries when shared isn't found<commit_after>#[doc = "

Finds crate binaries and loads their metadata

"];

import driver::session;
import session::session;
import syntax::{ast, attr};
import syntax::print::pprust;
import syntax::codemap::span;
import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
import util::{filesearch};
import io::writer_util;

export load_library_crate;
export list_file_metadata;
export note_linkage_attrs;
export crate_name_from_metas;
export metadata_matches;

fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
                      metas: [@ast::meta_item], hash: str)
   -> {ident: str, data: @[u8]} {

    alt find_library_crate(sess, span, metas, hash) {
      some(t) { ret t; }
      none {
        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
      }
    }
}

fn find_library_crate(sess: session::session, span: span,
                      metas: [@ast::meta_item], hash: str)
   -> option<{ident: str, data: @[u8]}> {

    attr::require_unique_names(sess.diagnostic(), metas);
    let metas = metas;

    let nn = default_native_lib_naming(sess, sess.opts.static);
    find_library_crate_aux(sess, span, nn,
                           metas, hash, sess.filesearch)
}

fn default_native_lib_naming(sess: session::session, static: bool) ->
   {prefix: str, suffix: str} {
    if static { ret {prefix: "lib", suffix: ".rlib"}; }
    alt sess.targ_cfg.os {
      session::os_win32 { ret {prefix: "", suffix: ".dll"}; }
      session::os_macos { ret {prefix: "lib", suffix: ".dylib"}; }
      session::os_linux { ret {prefix: "lib", suffix: ".so"}; }
      session::os_freebsd { ret {prefix: "lib", suffix: ".so"}; }
    }
}

fn find_library_crate_aux(sess: session::session,
                          span: span,
                          nn: {prefix: str, suffix: str},
                          metas: [@ast::meta_item],
                          hash: str,
                          filesearch: filesearch::filesearch) ->
   option<{ident: str, data: @[u8]}> {
    let crate_name = crate_name_from_metas(metas);
    let prefix: str = nn.prefix + crate_name + "-";
    let suffix: str = nn.suffix;

    let mut matches = [];
    filesearch::search(filesearch, { |path|
        #debug("inspecting file %s", path);
        let f: str = path::basename(path);
        if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
            #debug("skipping %s, doesn't look like %s*%s", path, prefix,
                   suffix);
            option::none::<()>
        } else {
            #debug("%s is a candidate", path);
            alt get_metadata_section(sess, path) {
              option::some(cvec) {
                if !crate_matches(cvec, metas, hash) {
                    #debug("skipping %s, metadata doesn't match", path);
                    option::none::<()>
                } else {
                    #debug("found %s with matching metadata", path);
                    matches += [{ident: path, data: cvec}];
                    option::none::<()>
                }
              }
              _ {
                #debug("could not load metadata for %s", path);
                option::none::<()>
              }
            }
        }
    });

    if matches.is_empty() {
        none
    } else if matches.len() == 1u {
        some(matches[0])
    } else {
        sess.span_err(
            span, #fmt("multiple matching crates for `%s`", crate_name));
        sess.note("candidates:");
        for matches.each {|match|
            sess.note(#fmt("path: %s", match.ident));
            let attrs = decoder::get_crate_attributes(match.data);
            note_linkage_attrs(sess, attrs);
        }
        sess.abort_if_errors();
        none
    }
}

fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
    let name_items = attr::find_meta_items_by_name(metas, "name");
    alt vec::last_opt(name_items) {
      some(i) {
        alt attr::get_meta_item_value_str(i) {
          some(n) { n }
          // FIXME: Probably want a warning here since the user
          // is using the wrong type of meta item (#2406)
          _ { fail }
        }
      }
      none { fail "expected to find the crate name" }
    }
}

fn note_linkage_attrs(sess: session::session, attrs: [ast::attribute]) {
    for attr::find_linkage_attrs(attrs).each {|attr|
        sess.note(#fmt("meta: %s", pprust::attr_to_str(attr)));
    }
}

fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
    bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);
    if hash.is_not_empty() {
        let chash = decoder::get_crate_hash(crate_data);
        if chash != hash { ret false; }
    }
    metadata_matches(linkage_metas, metas)
}

fn metadata_matches(extern_metas: [@ast::meta_item],
                    local_metas: [@ast::meta_item]) -> bool {

    #debug("matching %u metadata requirements against %u items",
           vec::len(local_metas), vec::len(extern_metas));

    #debug("crate metadata:");
    for extern_metas.each {|have|
        #debug("  %s", pprust::meta_item_to_str(*have));
    }

    for local_metas.each {|needed|
        #debug("looking for %s", pprust::meta_item_to_str(*needed));
        if !attr::contains(extern_metas, needed) {
            #debug("missing %s", pprust::meta_item_to_str(*needed));
            ret false;
        }
    }
    ret true;
}

fn get_metadata_section(sess: session::session,
                        filename: str) -> option<@[u8]> unsafe {
    let mb = str::as_c_str(filename, {|buf|
        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
                                   });
    if mb as int == 0 { ret option::none::<@[u8]>; }
    let of = alt mk_object_file(mb) {
        option::some(of) { of }
        _ { ret option::none::<@[u8]>; }
    };
    let si = mk_section_iter(of.llof);
    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
        let name_buf = llvm::LLVMGetSectionName(si.llsi);
        let name = unsafe { str::unsafe::from_c_str(name_buf) };
        if str::eq(name, sess.targ_cfg.target_strs.meta_sect_name) {
            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
            let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
            unsafe {
                let cvbuf: *u8 = unsafe::reinterpret_cast(cbuf);
                ret some(@vec::unsafe::from_buf(cvbuf, csz));
            }
        }
        llvm::LLVMMoveToNextSection(si.llsi);
    }
    ret option::none::<@[u8]>;
}

// A diagnostic function for dumping crate metadata to an output stream
fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
    alt get_metadata_section(sess, path) {
      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
      option::none {
        out.write_str("could not find metadata in " + path + ".\n");
      }
    }
}
<|endoftext|>