<commit_before>#![deny(warnings)]
#![feature(phase)]

#[phase(plugin, link)]
extern crate log;

use std::io::TempDir;
use std::io::fs::{PathExtensions, mod};
use std::io::process::{Command, ExitSignal, ExitStatus, InheritFd, ProcessOutput};
use std::os;

fn main() {
    let args = os::args();
    let args = args.slice_from(1);

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| arg.as_slice() != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(args);
        cmd.stdout(InheritFd(1));
        cmd.stderr(InheritFd(2));

        info!("cwd: . | cmd: `{}`", cmd);
        match cmd.output() {
            Err(e) => fail!("`{}` failed: {}", cmd, e),
            Ok(ProcessOutput { status: exit, .. }) =>  {
                let exit_code = match exit {
                    ExitSignal(code) => code,
                    ExitStatus(code) => code,
                };

                os::set_exit_status(exit_code);

                return;
            },
        }
    }

    // Before `--`: arguments for the compiler
    // After `--`: arguments for the executable
    let mut splitted_args = args.split(|arg| arg.as_slice() == "--");
    let compiler_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if compiler_args.iter().any(|arg| arg.as_slice() == "--out-dir") {
        fail!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = os::getcwd();
    for arg in compiler_args.iter().map(|arg| arg.as_slice()).filter(|&arg| arg != "--run") {
        let path = Path::new(arg);
        if path.exists() && path.is_relative() {
            cmd.arg(current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Create temporary directory
    let temp_dir = TempDir::new("rust").unwrap();
    let temp_dir_path = temp_dir.path();
    let temp_dir_display = temp_dir_path.display();

    // Compile
    info!("cwd: {} | cmd: `{}`", temp_dir_display, cmd);
    match cmd.cwd(temp_dir_path).output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::readdir(temp_dir_path) {
        Err(e) => fail!("`ls {}` failed: {}", temp_dir_display, e),
        Ok(paths) => match paths.as_slice().get(0) {
            Some(path) => Command::new(path),
            None => fail!("no binary found in {}", temp_dir_display),
        }
    };

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }
    cmd.stdin(InheritFd(0));
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Execute
    info!("cwd: . | cmd: `{}`", cmd);
    match cmd.output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }
}
<commit_msg>fix(main): rename `fail!` to `panic!`<commit_after>#![deny(warnings)]
#![feature(phase)]

#[phase(plugin, link)]
extern crate log;

use std::io::TempDir;
use std::io::fs::{PathExtensions, mod};
use std::io::process::{Command, ExitSignal, ExitStatus, InheritFd, ProcessOutput};
use std::os;

fn main() {
    let args = os::args();
    let args = args.slice_from(1);

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| arg.as_slice() != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(args);
        cmd.stdout(InheritFd(1));
        cmd.stderr(InheritFd(2));

        info!("cwd: . | cmd: `{}`", cmd);
        match cmd.output() {
            Err(e) => panic!("`{}` failed: {}", cmd, e),
            Ok(ProcessOutput { status: exit, .. }) =>  {
                let exit_code = match exit {
                    ExitSignal(code) => code,
                    ExitStatus(code) => code,
                };

                os::set_exit_status(exit_code);

                return;
            },
        }
    }

    // Before `--`: arguments for the compiler
    // After `--`: arguments for the executable
    let mut splitted_args = args.split(|arg| arg.as_slice() == "--");
    let compiler_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if compiler_args.iter().any(|arg| arg.as_slice() == "--out-dir") {
        panic!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = os::getcwd();
    for arg in compiler_args.iter().map(|arg| arg.as_slice()).filter(|&arg| arg != "--run") {
        let path = Path::new(arg);
        if path.exists() && path.is_relative() {
            cmd.arg(current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Create temporary directory
    let temp_dir = TempDir::new("rust").unwrap();
    let temp_dir_path = temp_dir.path();
    let temp_dir_display = temp_dir_path.display();

    // Compile
    info!("cwd: {} | cmd: `{}`", temp_dir_display, cmd);
    match cmd.cwd(temp_dir_path).output() {
        Err(e) => panic!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::readdir(temp_dir_path) {
        Err(e) => panic!("`ls {}` failed: {}", temp_dir_display, e),
        Ok(paths) => match paths.as_slice().get(0) {
            Some(path) => Command::new(path),
            None => panic!("no binary found in {}", temp_dir_display),
        }
    };

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }
    cmd.stdin(InheritFd(0));
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Execute
    info!("cwd: . | cmd: `{}`", cmd);
    match cmd.output() {
        Err(e) => panic!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#![deny(warnings)]

#[macro_use]
extern crate clap;
extern crate rand;

use clap::{App, Arg};

static EFF_WORDLIST: &'static str = include_str!(concat!(env!("OUT_DIR"), "/eff_wordlist.txt"));

fn parse_diceware_list(input: &str) -> Vec<&str> {
    input.lines().map(|l| l.split_whitespace().last().unwrap()).collect()
}

fn main() {
    let matches = App::new("xkpwgen")
        .version(&crate_version!())
        .about("Generate XKCD 936 passwords")
        .after_help("Copyright (C) 2017 Sebastian Wiesner <swiesner@lunaryorn.com>
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.")
        .get_matches();

    let words = parse_diceware_list(EFF_WORDLIST);
    println!("{}",
             rand::sample(&mut rand::thread_rng(), words, 4).join(" "));
}
<commit_msg>Fix warnings<commit_after>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#![deny(warnings)]

#[macro_use]
extern crate clap;
extern crate rand;

use clap::{App};

static EFF_WORDLIST: &'static str = include_str!(concat!(env!("OUT_DIR"), "/eff_wordlist.txt"));

fn parse_diceware_list(input: &str) -> Vec<&str> {
    input.lines().map(|l| l.split_whitespace().last().unwrap()).collect()
}

fn main() {
    App::new("xkpwgen")
        .version(&crate_version!())
        .about("Generate XKCD 936 passwords")
        .after_help("Copyright (C) 2017 Sebastian Wiesner <swiesner@lunaryorn.com>
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.")
        .get_matches();

    let words = parse_diceware_list(EFF_WORDLIST);
    println!("{}",
             rand::sample(&mut rand::thread_rng(), words, 4).join(" "));
}
<|endoftext|>


<commit_before>// Bytecode instructions
const OP_LOAD: u8 = 1; // arity: 2 - (value: u64, dest: u8)
const OP_ADD: u8 = 2; // arity: 3 - (a: u8, b: u8, dest: u8)
const OP_PRINT: u8 = 3; // arity: 1 - (reg: u8)
const OP_RETURN: u8 = 4; // arity: 1 - (reg: u8)

fn interpret(code: &[u8]) -> u64 {
    let mut pc = 0; // "Program counter", the index of the current instruction.
    let mut regs = [0u64; 256]; // Array of 256 zeros.

    loop {
        let op = code[pc];
        pc += 1;
        match op {
            OP_LOAD => {
                // Read 64 bits from the code (BUG: right now I'm only reading
                // one byte of the number!
                let val = code[pc] as u64;
                pc += 8;
                let dest = code[pc] as usize;
                pc += 1;
                regs[dest] = val;
            },
            OP_ADD => {
                let a = code[pc] as usize;
                pc += 1;
                let b = code[pc] as usize;
                pc += 1;
                let dest = code[pc] as usize;
                pc += 1;
                regs[dest] = regs[a] + regs[b];
            },
            OP_PRINT => {
                let r = code[pc] as usize;
                pc += 1;
                println!("{}", regs[r]);
            },
            OP_RETURN => {
                let r = code[pc] as usize;
                pc += 1;
                return regs[r];
            },
            _ => panic!("Invalid opcode at offset {}", pc)
        }
    }
}

fn main() {
    let code = [
        OP_LOAD, 73, 0, 0, 0, 0, 0, 0, 0, 0, // load the number 73 into R0.
        OP_LOAD, 68, 0, 0, 0, 0, 0, 0, 0, 1, // load the number 68 into R1.
        OP_ADD, 0, 1, 2, // compute R0 + R1 and store it in R2.
        OP_PRINT, 2,
        OP_RETURN, 2
    ];

    interpret(&code); // should print 73 + 68, which is 141.
}
<commit_msg>Remove OP_PRINT and just print the return in main() for now<commit_after>// Bytecode instructions
const OP_LOAD: u8 = 1; // arity: 2 - (value: u64, dest: u8)
const OP_ADD: u8 = 2; // arity: 3 - (a: u8, b: u8, dest: u8)
const OP_RETURN: u8 = 3; // arity: 1 - (reg: u8)

fn interpret(code: &[u8]) -> u64 {
    let mut pc = 0; // "Program counter", the index of the current instruction.
    let mut regs = [0u64; 256]; // Array of 256 zeros.

    loop {
        let op = code[pc];
        pc += 1;
        match op {
            OP_LOAD => {
                // Read 64 bits from the code (BUG: right now I'm only reading
                // one byte of the number!
                let val = code[pc] as u64;
                pc += 8;
                let dest = code[pc] as usize;
                pc += 1;
                regs[dest] = val;
            },
            OP_ADD => {
                let a = code[pc] as usize;
                pc += 1;
                let b = code[pc] as usize;
                pc += 1;
                let dest = code[pc] as usize;
                pc += 1;
                regs[dest] = regs[a] + regs[b];
            },
            OP_RETURN => {
                let r = code[pc] as usize;
                return regs[r];
            },
            _ => panic!("Invalid opcode at offset {}", pc)
        }
    }
}

fn main() {
    let code = [
        OP_LOAD, 73, 0, 0, 0, 0, 0, 0, 0, 0, // load the number 73 into R0.
        OP_LOAD, 68, 0, 0, 0, 0, 0, 0, 0, 1, // load the number 68 into R1.
        OP_ADD, 0, 1, 2, // compute R0 + R1 and store it in R2.
        OP_RETURN, 2
    ];

    // should print 73 + 68, which is 141.
    println!("{}", interpret(&code))
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
#[macro_use]
extern crate log;

extern crate env_logger;
extern crate freetype;
extern crate genmesh;
extern crate image;
extern crate nalgebra;
extern crate obj;
extern crate time;

mod camera;
mod draw;
mod shader;

use std::{mem, thread};
use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::rc::Rc;

use camera::Camera;
use draw::{Cube, Grid, GameObject, Text};
use shader::{ShaderType, FragmentShaderType, VertexShaderType};

use freetype as ft;

use glium::{glutin, Display, DisplayBuild, DrawError, Program, Surface};
use glium::glutin::{ElementState, VirtualKeyCode};
use glium::texture::{ClientFormat, RawImage2d, Texture2d};

use nalgebra::{zero, BaseFloat, Vec3};

struct Scene<'a> {
    // TODO: Do we want this to be GameObject + 'a?
    named_objects: HashMap<String, Box<GameObject + 'a>>,
    unamed_objects: Vec<Box<GameObject + 'a>>,
    camera: Camera,
}

impl<'a> Scene<'a> {
    fn new(camera: Camera) -> Self {
        Scene { camera: camera, named_objects: HashMap::new(), unamed_objects: Vec::new() }
    }

    fn update(&mut self) {
        for obj in self.named_objects.iter_mut().map(|(_, v)| v)
            .chain(self.unamed_objects.iter_mut()) {
            obj.update();
        }
    }

    fn draw(&self, ctxt: &mut EngineContext) {
        let mut target = ctxt.display.draw();
        target.clear_color_and_depth((0., 0., 0., 1.), 1.);
        for obj in self.named_objects.values().chain(self.unamed_objects.iter()) {
            ctxt.draw(&mut target, &self.camera, obj).unwrap();
        }
        target.finish().unwrap();
    }

    fn add<G: GameObject + 'a>(&mut self, object: G) {
        if object.name().is_empty() {
            self.unamed_objects.push(Box::new(object));
        } else {
            assert!(self.named_objects.insert(object.name().to_owned(),
                                              Box::new(object)).is_none(),
                    "Duplicate object name");
        }
    }

    fn add_text(&mut self, text: Text<'static>) {
        for c in text.into_chars() {
            self.add(c);
        }
    }

    unsafe fn get_object<T: GameObject>(&self, name: &str) -> Option<&T> {
        self.named_objects.get(name).map(|o| mem::transmute(o))
    }
}

const RELATIVE_ROTATION: bool = true;

pub fn get_display_dim(display: &Display) -> (u32, u32) {
    match display.get_window().unwrap().get_inner_size() {
        Some(dim) => dim,
        None => panic!("Couldn't get window dimensions")
    }
}

pub struct EngineContext {
    display: Display,
    vert_shader_map: HashMap<VertexShaderType, String>,
    frag_shader_map: HashMap<FragmentShaderType, String>,
    texture_cache: TextureCache,
}

pub struct TextureCache {
    cache: HashMap<&'static str, Rc<Texture2d>>,
    glyph_cache: HashMap<char, Rc<Character>>,
}

pub struct Character {
    left: f32,
    top: f32,
    width: f32,
    height: f32,
    advance_x: f32,
    advance_y: f32,
    texture: Texture2d,
}

impl TextureCache {
    fn new() -> Self {
        TextureCache { cache: HashMap::new(), glyph_cache: HashMap::new() }
    }

    fn get_texture(&mut self, display: &Display, name: &'static str) -> Rc<Texture2d> {
        self.cache.entry(name).or_insert_with(|| {
            let f = File::open(name).unwrap();
            let image = image::load(f, image::PNG).unwrap();
            Rc::new(Texture2d::new(display, image))
        }).clone()
    }

    fn get_glyph(&mut self, display: &Display, face: &ft::Face, c: char) -> Rc<Character> {
        self.glyph_cache.entry(c).or_insert_with(|| {
            face.load_char(c as usize, ft::face::RENDER).unwrap();
            let g = face.glyph();

            let bitmap = g.bitmap();
            Rc::new(Character {
                left: g.bitmap_left() as f32,
                top: g.bitmap_top() as f32,
                width: bitmap.width() as f32,
                height: bitmap.rows() as f32,
                advance_x: (g.advance().x >> 6) as f32,
                advance_y: (g.advance().y >> 6) as f32,
                texture: Texture2d::new(display, RawImage2d {
                    data: Cow::Borrowed(bitmap.buffer()),
                    width: bitmap.width() as u32, height: bitmap.rows() as u32,
                    format: ClientFormat::U8
                })
            })
        }).clone()
    }
}

impl EngineContext {
    pub fn new(display: Display) -> Self {
        EngineContext { display: display, vert_shader_map: HashMap::new(),
                        frag_shader_map: HashMap::new(), texture_cache: TextureCache::new() }
    }

    pub fn draw<S: Surface>(&mut self, surface: &mut S, camera: &Camera,
                            obj: &Box<GameObject>) -> Result<(), DrawError> {
        let parent = obj.parent();

        let &mut EngineContext { ref display, ref mut vert_shader_map,
                                 ref mut frag_shader_map, .. } = self;
        let vertex_shader = Self::get_shader(vert_shader_map, parent.vert_shader_type);
        let fragment_shader = Self::get_shader(frag_shader_map, parent.frag_shader_type);
        let program = Program::from_source(display, vertex_shader, fragment_shader, None).unwrap();

        let uniforms = obj.construct_uniforms(&camera);

        surface.draw(&parent.vertex_buffer, parent.indices.clone(), &program, &uniforms,
                     &parent.draw_params)
    }

    fn get_shader<S: ShaderType>(shader_map: &mut HashMap<S, String>, shader_type: S) -> &str {
        shader_map.entry(shader_type).or_insert_with(|| {
            let mut shader = String::new();
            File::open(shader_type.to_filename()).unwrap().read_to_string(&mut shader).unwrap();
            shader
        })
    }
}

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

    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 600)
        .with_title(format!("3D Cube"))
        .build_glium()
        .unwrap();

    let camera = {
        let (w, h) = get_display_dim(&display);
        let (w, h) = (w as f32, h as f32);
        Camera::new(Vec3::new(0., 0., 1.), w / h)
    };

    let mut ctxt = EngineContext::new(display);

    let mut scene = Scene::new(camera);
    let mut g = Grid::new(&ctxt.display, 20);
    g.parent.name = "grid".to_owned();
    scene.add(g);
    scene.add(Cube::new(&mut ctxt, 1., zero()));

    // FIXME: Text needs to go last
    scene.add_text(Text::new(&mut ctxt, -0.9, -0.9, "Frame rate: 60fps"));

    let mut right_mouse_pressed = false;
    let mut left_mouse_pressed = false;
    let mut old_mouse_coords = None;

    let mut accumulator = 0;
    let mut previous_time = time::precise_time_ns();
    loop {
        for ev in ctxt.display.poll_events() {
            match ev {
                glutin::Event::KeyboardInput(ElementState::Pressed, _, Some(key)) => {
                    match key {
                        VirtualKeyCode::R => {
                            scene.camera.set_pos(&Vec3::new(0., 0., 1.));
                            scene.camera.set_abs_rotation(0., 0.);
                            scene.camera.set_fov(BaseFloat::frac_pi_2());
                        }
                        _ => ()
                    }
                },
                glutin::Event::MouseWheel(glutin::MouseScrollDelta::LineDelta(_, v)) => {
                    let fov = scene.camera.fov();
                    let frac: f32 = (f32::pi() - fov) / f32::pi();
                    let new_fov = f32::max(0., fov + 0.05 * frac * v);
                    scene.camera.set_fov(new_fov);
                },
                glutin::Event::MouseMoved((x, y)) => {
                    if right_mouse_pressed {
                        // Rotation
                        let (x, y) = (x as f32, y as f32);
                        let (w, h) = get_display_dim(&ctxt.display);
                        let (w, h) = (w as f32, h as f32);
                        if !RELATIVE_ROTATION {
                            let pitch = (y / h) * f32::two_pi();
                            let yaw = (x / w) * f32::two_pi();
                            scene.camera.set_abs_rotation(pitch, -yaw);
                        } else {
                            if let Some((x_old, y_old)) = old_mouse_coords {
                                let delta_x = x - x_old;
                                let delta_y = y - y_old;

                                let pitch = (delta_y * 0.5 / h) * f32::two_pi();
                                let yaw = (delta_x * 0.5 / w) * f32::two_pi();
                                scene.camera.rotate(pitch, yaw);
                            }
                            old_mouse_coords = Some((x, y));
                        }
                    } else if left_mouse_pressed {
                        // Translation
                        let (x, y) = (x as f32, y as f32);
                        if let Some((x_old, y_old)) = old_mouse_coords {
                            let diff = Vec3::new(x_old - x, y - y_old, 0.) * 0.003 as f32;
                            scene.camera.translate(&diff);
                        }
                        old_mouse_coords = Some((x, y));
                    }
                },
                glutin::Event::MouseInput(state, button) => {
                    if state == ElementState::Released {
                        old_mouse_coords = None;
                    };

                    match button {
                        glutin::MouseButton::Left =>
                            left_mouse_pressed = state == ElementState::Pressed,
                        glutin::MouseButton::Right =>
                            right_mouse_pressed = state == ElementState::Pressed,
                        _ => ()
                    }
                }
                glutin::Event::Resized(x, y) => {
                    scene.camera.set_aspect_ratio(x as f32 / y as f32);
                },
                glutin::Event::Closed => return,
                _ => ()
            }
        }

        let now = time::precise_time_ns();
        let delta = now - previous_time;
        accumulator += delta;
        previous_time = now;

        const FPS: u64 = 60;
        const FIXED_TIME_STAMP: u64 = 10e9 as u64 / FPS;
        if accumulator >= FIXED_TIME_STAMP {
            while accumulator >= FIXED_TIME_STAMP {
                accumulator -= FIXED_TIME_STAMP;
                scene.update();
            }
            scene.draw(&mut ctxt);
        }

        // A half-assed attempt to not use up the entire CPU and still keep the frame rate
        let sleep_time = ((FIXED_TIME_STAMP - accumulator) / 1000000) as i32;
        if sleep_time > 30 {
            let sleep_time = sleep_time * 3 / 5;
            thread::sleep_ms(sleep_time as u32);
        }
    }
}
<commit_msg>Fixed game loop framerate bug<commit_after>#[macro_use]
extern crate glium;
#[macro_use]
extern crate log;

extern crate env_logger;
extern crate freetype;
extern crate genmesh;
extern crate image;
extern crate nalgebra;
extern crate obj;
extern crate time;

mod camera;
mod draw;
mod shader;

use std::{mem, thread};
use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::rc::Rc;

use camera::Camera;
use draw::{Cube, Grid, GameObject, Text};
use shader::{ShaderType, FragmentShaderType, VertexShaderType};

use freetype as ft;

use glium::{glutin, Display, DisplayBuild, DrawError, Program, Surface};
use glium::glutin::{ElementState, VirtualKeyCode};
use glium::texture::{ClientFormat, RawImage2d, Texture2d};

use nalgebra::{zero, BaseFloat, Vec3};

struct Scene<'a> {
    // TODO: Do we want this to be GameObject + 'a?
    named_objects: HashMap<String, Box<GameObject + 'a>>,
    unamed_objects: Vec<Box<GameObject + 'a>>,
    camera: Camera,
}

impl<'a> Scene<'a> {
    fn new(camera: Camera) -> Self {
        Scene { camera: camera, named_objects: HashMap::new(), unamed_objects: Vec::new() }
    }

    fn update(&mut self) {
        for obj in self.named_objects.iter_mut().map(|(_, v)| v)
            .chain(self.unamed_objects.iter_mut()) {
            obj.update();
        }
    }

    fn draw(&self, ctxt: &mut EngineContext) {
        let mut target = ctxt.display.draw();
        target.clear_color_and_depth((0., 0., 0., 1.), 1.);
        for obj in self.named_objects.values().chain(self.unamed_objects.iter()) {
            ctxt.draw(&mut target, &self.camera, obj).unwrap();
        }
        target.finish().unwrap();
    }

    fn add<G: GameObject + 'a>(&mut self, object: G) {
        if object.name().is_empty() {
            self.unamed_objects.push(Box::new(object));
        } else {
            assert!(self.named_objects.insert(object.name().to_owned(),
                                              Box::new(object)).is_none(),
                    "Duplicate object name");
        }
    }

    fn add_text(&mut self, text: Text<'static>) {
        for c in text.into_chars() {
            self.add(c);
        }
    }

    unsafe fn get_object<T: GameObject>(&self, name: &str) -> Option<&T> {
        self.named_objects.get(name).map(|o| mem::transmute(o))
    }
}

const RELATIVE_ROTATION: bool = true;

pub fn get_display_dim(display: &Display) -> (u32, u32) {
    match display.get_window().unwrap().get_inner_size() {
        Some(dim) => dim,
        None => panic!("Couldn't get window dimensions")
    }
}

pub struct EngineContext {
    display: Display,
    vert_shader_map: HashMap<VertexShaderType, String>,
    frag_shader_map: HashMap<FragmentShaderType, String>,
    texture_cache: TextureCache,
}

pub struct TextureCache {
    cache: HashMap<&'static str, Rc<Texture2d>>,
    glyph_cache: HashMap<char, Rc<Character>>,
}

pub struct Character {
    left: f32,
    top: f32,
    width: f32,
    height: f32,
    advance_x: f32,
    advance_y: f32,
    texture: Texture2d,
}

impl TextureCache {
    fn new() -> Self {
        TextureCache { cache: HashMap::new(), glyph_cache: HashMap::new() }
    }

    fn get_texture(&mut self, display: &Display, name: &'static str) -> Rc<Texture2d> {
        self.cache.entry(name).or_insert_with(|| {
            let f = File::open(name).unwrap();
            let image = image::load(f, image::PNG).unwrap();
            Rc::new(Texture2d::new(display, image))
        }).clone()
    }

    fn get_glyph(&mut self, display: &Display, face: &ft::Face, c: char) -> Rc<Character> {
        self.glyph_cache.entry(c).or_insert_with(|| {
            face.load_char(c as usize, ft::face::RENDER).unwrap();
            let g = face.glyph();

            let bitmap = g.bitmap();
            Rc::new(Character {
                left: g.bitmap_left() as f32,
                top: g.bitmap_top() as f32,
                width: bitmap.width() as f32,
                height: bitmap.rows() as f32,
                advance_x: (g.advance().x >> 6) as f32,
                advance_y: (g.advance().y >> 6) as f32,
                texture: Texture2d::new(display, RawImage2d {
                    data: Cow::Borrowed(bitmap.buffer()),
                    width: bitmap.width() as u32, height: bitmap.rows() as u32,
                    format: ClientFormat::U8
                })
            })
        }).clone()
    }
}

impl EngineContext {
    pub fn new(display: Display) -> Self {
        EngineContext { display: display, vert_shader_map: HashMap::new(),
                        frag_shader_map: HashMap::new(), texture_cache: TextureCache::new() }
    }

    pub fn draw<S: Surface>(&mut self, surface: &mut S, camera: &Camera,
                            obj: &Box<GameObject>) -> Result<(), DrawError> {
        let parent = obj.parent();

        let &mut EngineContext { ref display, ref mut vert_shader_map,
                                 ref mut frag_shader_map, .. } = self;
        let vertex_shader = Self::get_shader(vert_shader_map, parent.vert_shader_type);
        let fragment_shader = Self::get_shader(frag_shader_map, parent.frag_shader_type);
        let program = Program::from_source(display, vertex_shader, fragment_shader, None).unwrap();

        let uniforms = obj.construct_uniforms(&camera);

        surface.draw(&parent.vertex_buffer, parent.indices.clone(), &program, &uniforms,
                     &parent.draw_params)
    }

    fn get_shader<S: ShaderType>(shader_map: &mut HashMap<S, String>, shader_type: S) -> &str {
        shader_map.entry(shader_type).or_insert_with(|| {
            let mut shader = String::new();
            File::open(shader_type.to_filename()).unwrap().read_to_string(&mut shader).unwrap();
            shader
        })
    }
}

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

    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 600)
        .with_title(format!("3D Cube"))
        .build_glium()
        .unwrap();

    let camera = {
        let (w, h) = get_display_dim(&display);
        let (w, h) = (w as f32, h as f32);
        Camera::new(Vec3::new(0., 0., 1.), w / h)
    };

    let mut ctxt = EngineContext::new(display);

    let mut scene = Scene::new(camera);
    let mut g = Grid::new(&ctxt.display, 20);
    g.parent.name = "grid".to_owned();
    scene.add(g);
    scene.add(Cube::new(&mut ctxt, 1., zero()));

    // FIXME: Text needs to go last
    scene.add_text(Text::new(&mut ctxt, -0.9, -0.9, "Frame rate: 60fps"));

    let mut right_mouse_pressed = false;
    let mut left_mouse_pressed = false;
    let mut old_mouse_coords = None;

    let mut accumulator = 0;
    let mut nframes = 0;
    let mut previous_time = time::precise_time_ns();
    let mut target_time = previous_time + 1e9 as u64;
    loop {
        for ev in ctxt.display.poll_events() {
            match ev {
                glutin::Event::KeyboardInput(ElementState::Pressed, _, Some(key)) => {
                    match key {
                        VirtualKeyCode::R => {
                            scene.camera.set_pos(&Vec3::new(0., 0., 1.));
                            scene.camera.set_abs_rotation(0., 0.);
                            scene.camera.set_fov(BaseFloat::frac_pi_2());
                        }
                        _ => ()
                    }
                },
                glutin::Event::MouseWheel(glutin::MouseScrollDelta::LineDelta(_, v)) => {
                    let fov = scene.camera.fov();
                    let frac: f32 = (f32::pi() - fov) / f32::pi();
                    let new_fov = f32::max(0., fov + 0.05 * frac * v);
                    scene.camera.set_fov(new_fov);
                },
                glutin::Event::MouseMoved((x, y)) => {
                    if right_mouse_pressed {
                        // Rotation
                        let (x, y) = (x as f32, y as f32);
                        let (w, h) = get_display_dim(&ctxt.display);
                        let (w, h) = (w as f32, h as f32);
                        if !RELATIVE_ROTATION {
                            let pitch = (y / h) * f32::two_pi();
                            let yaw = (x / w) * f32::two_pi();
                            scene.camera.set_abs_rotation(pitch, -yaw);
                        } else {
                            if let Some((x_old, y_old)) = old_mouse_coords {
                                let delta_x = x - x_old;
                                let delta_y = y - y_old;

                                let pitch = (delta_y * 0.5 / h) * f32::two_pi();
                                let yaw = (delta_x * 0.5 / w) * f32::two_pi();
                                scene.camera.rotate(pitch, yaw);
                            }
                            old_mouse_coords = Some((x, y));
                        }
                    } else if left_mouse_pressed {
                        // Translation
                        let (x, y) = (x as f32, y as f32);
                        if let Some((x_old, y_old)) = old_mouse_coords {
                            let diff = Vec3::new(x_old - x, y - y_old, 0.) * 0.003 as f32;
                            scene.camera.translate(&diff);
                        }
                        old_mouse_coords = Some((x, y));
                    }
                },
                glutin::Event::MouseInput(state, button) => {
                    if state == ElementState::Released {
                        old_mouse_coords = None;
                    };

                    match button {
                        glutin::MouseButton::Left =>
                            left_mouse_pressed = state == ElementState::Pressed,
                        glutin::MouseButton::Right =>
                            right_mouse_pressed = state == ElementState::Pressed,
                        _ => ()
                    }
                }
                glutin::Event::Resized(x, y) => {
                    scene.camera.set_aspect_ratio(x as f32 / y as f32);
                },
                glutin::Event::Closed => return,
                _ => ()
            }
        }

        let now = time::precise_time_ns();
        let delta = now - previous_time;
        accumulator += delta;
        previous_time = now;

        const FPS: u64 = 30;
        const FIXED_TIME_STAMP: u64 = 1e9 as u64 / FPS;
        if accumulator >= FIXED_TIME_STAMP {
            while accumulator >= FIXED_TIME_STAMP {
                accumulator -= FIXED_TIME_STAMP;
                scene.update();
            }
            scene.draw(&mut ctxt);
            nframes += 1;
            let now = time::precise_time_ns();
            if now > target_time {
                target_time = now + 1e9 as u64;
                debug!("fps: {}", nframes);
                nframes = 0;
            }
        }
    }
}
<|endoftext|>


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

mod logger;
mod toml_file;
mod git;
mod changelog;
mod commit_analyzer;
mod cargo;
mod error;
mod github;
mod config;
mod utils;

extern crate rustc_serialize;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate docopt;
extern crate git2;
extern crate clog;
extern crate hyper;
extern crate hubcaps;
extern crate url;
extern crate travis_after_all;
extern crate env_logger;

use docopt::Docopt;
use commit_analyzer::CommitType;
use config::ConfigBuilder;
use std::process;
use semver::Version;
use std::{env,fs};
use std::path::Path;
use std::error::Error;
use std::thread;
use std::time::Duration;
use travis_after_all::Build;
use utils::user_repo_from_url;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USERAGENT: &'static str = concat!("semantic-rs/", env!("CARGO_PKG_VERSION"));
const USAGE: &'static str = "
semantic.rs 🚀

Usage:
  semantic-rs [options]
  semantic-rs --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  -p PATH, --path=PATH   Specifies the repository path. [default: .]
  -w W, --write=W        Write changes to files (default: yes if CI is set, otherwise no).
  -r R, --release=R      Create release on GitHub and publish on crates.io (only in write mode) [default: yes].
  -b B, --branch=B       The branch on which releases should happen. [default: master].
";

const COMMITTER_ERROR_MESSAGE: &'static str = r"
A release commit needs a committer name and email address.
We tried fetching it from different locations, but couldn't find one.

Committer information is taken from the following environment variables, if set:

GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL

If none is set the normal git config is tried in the following order:

Local repository config
User config
Global config";

macro_rules! print_exit {
    ($fmt:expr) => {{
        logger::stderr($fmt);
        process::exit(1);
    }};
    ($fmt:expr, $($arg:tt)*) => {{
        logger::stderr(format!($fmt, $($arg)*));
        process::exit(1);
    }};
}

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_path: String,
    flag_write: Option<String>,
    flag_version: bool,
    flag_release: String,
    flag_branch: String,
}

fn string_to_bool(answer: &str) -> bool {
    match &answer.to_lowercase()[..] {
        "yes" | "true" | "1" => true,
        _ => false
    }
}

fn version_bump(version: &Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

fn ci_env_set() -> bool {
    env::var("CI").is_ok()
}

fn current_branch(repo: &git2::Repository) -> Option<String> {
    if let Ok(branch) = env::var("TRAVIS_BRANCH") {
        return Some(branch)
    }

    let head = repo.head().expect("No HEAD found for repository");

    if head.is_branch() {
        let short = head.shorthand().expect("No branch name found");
        return Some(short.into());
    }

    None
}

fn is_release_branch(current: &str, release: &str) -> bool {
    if let Ok(pr) = env::var("TRAVIS_PULL_REQUEST") {
        if pr != "false" {
            return false;
        }
    }

    current == release
}

fn push_to_github(config: &config::Config, tag_name: &str) {
    logger::stdout("Pushing new commit and tag");
    git::push(&config, &tag_name)
        .unwrap_or_else(|err| print_exit!("Failed to push git: {:?}", err));

    logger::stdout("Waiting a tiny bit, so GitHub can store the git tag");
    thread::sleep(Duration::from_secs(1));
}

fn release_on_github(config: &config::Config, tag_message: &str, tag_name: &str) {
    if github::can_release(&config) {
        logger::stdout("Creating GitHub release");
        github::release(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create GitHub release: {:?}", err));
    } else {
        logger::stdout("Project not hosted on GitHub. Skipping release step");
    }
}

fn release_on_cratesio(config: &config::Config) {
    logger::stdout("Publishing crate on crates.io");
    if !cargo::publish(&config.repository_path, &config.cargo_token.as_ref().unwrap()) {
        print_exit!("Failed to publish on crates.io");
    }
}

fn generate_changelog(repository_path: &str, version: &Version, new_version: &String) -> String {
    logger::stdout(format!("New version would be: {}", new_version));
    logger::stdout("Would write the following Changelog:");
    match changelog::generate(repository_path, &version.to_string(), new_version) {
        Ok(log) => log,
        Err(err) => {
            logger::stderr(format!("Generating Changelog failed: {:?}", err));
            process::exit(1)
        }
    }
}

fn write_changelog(repository_path: &str, version: &Version, new_version: &str) {
    logger::stdout("Writing Changelog");
    changelog::write(repository_path, &version.to_string(), &new_version)
        .unwrap_or_else(|err| print_exit!("Writing Changelog failed: {:?}", err));
}

fn print_changelog(changelog: &str) {
    logger::stdout("====================================");
    logger::stdout(changelog);
    logger::stdout("====================================");
    logger::stdout("Would create annotated git tag");
}

fn package_crate(config: &config::Config, repository_path: &str, new_version: &str) {
    if config.release_mode {
        logger::stdout("Updating lockfile");
        if !cargo::update_lockfile(repository_path) {
            print_exit!("`cargo fetch` failed. See above for the cargo error message.");
        }
    }

    logger::stdout("Package crate");
    if !cargo::package(repository_path) {
        print_exit!("`cargo package` failed. See above for the cargo error message.");
    }

    git::commit_files(&config, &new_version)
        .unwrap_or_else(|err| print_exit!("Committing files failed: {:?}", err));
}

fn main() {
    env_logger::init().expect("Can't instantiate env logger");

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

    let mut config_builder = ConfigBuilder::new();

    if args.flag_version {
        println!("semantic.rs 🚀 -- v{}", VERSION);
        process::exit(0);
    }

    // If write mode is requested OR denied,
    // adhere to the user's wish,
    // otherwise we decide based on whether we are running in CI.
    let write_mode = match args.flag_write {
        None => ci_env_set(),
        Some(ref flag) => string_to_bool(flag)
    };

    // We can only release, if we are allowed to write
    let release_mode = write_mode && string_to_bool(&args.flag_release);

    config_builder.write(write_mode);
    config_builder.release(release_mode);
    config_builder.branch(args.flag_branch);

    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");
    let path = Path::new(&args.flag_path);
    let path = fs::canonicalize(path)
        .unwrap_or_else(|_| print_exit!("Path does not exist or a component is not a directory"));
    let repository_path = path.to_str()
        .unwrap_or_else(|| print_exit!("Path is not valid unicode"));

    let repo = match git2::Repository::open(repository_path) {
        Ok(repo) => repo,
        Err(e) => {
            logger::stderr(format!("Could not open the git repository: {:?}", e));
            process::exit(1);
        }
    };

    config_builder.repository_path(repository_path.to_owned());

    // extra scope scope to make sure borrow of `repo` is dropped
    {
        let signature = match git::get_signature(&repo) {
            Ok(sig) => sig,
            Err(e) => {
                logger::stderr(format!("Failed to get the committer's name and email address: {}", e.description()));
                logger::stderr(COMMITTER_ERROR_MESSAGE);
                process::exit(1);
            }
        };

        config_builder.signature(signature.to_owned());
    }

    // In case we are in write-mode AND release mode,
    // we will make sure we got all configuration settings
    if write_mode && release_mode {
        let remote_or_none = repo.find_remote("origin");
        match remote_or_none {
            Ok(remote) => {
                let url = remote.url().expect("Remote URL is not valid UTF-8").to_owned();
                let (user, repo_name) = user_repo_from_url(&url)
                    .unwrap_or_else(|e| print_exit!("Could not extract user and repository name from URL: {:?}", e));
                config_builder.user(user);
                config_builder.repository_name(repo_name);

                if github::is_github_url(&url) {
                    let gh_token = env::var("GH_TOKEN")
                        .unwrap_or_else(|err| print_exit!("GH_TOKEN not set: {:?}", err));
                    config_builder.gh_token(gh_token);
                }

                let cargo_token = env::var("CARGO_TOKEN")
                    .unwrap_or_else(|err| print_exit!("CARGO_TOKEN not set: {:?}", err));

                config_builder.cargo_token(cargo_token);
            },
            Err(err) => {
                logger::warn(format!("Could not determine the origin remote url: {:?}", err));
                logger::warn("semantic-rs can't push changes or create a release on GitHub");
            }
        }
    }

    config_builder.repository(repo);
    let config = config_builder.build();

    let branch = current_branch(&config.repository)
        .unwrap_or_else(|| print_exit!("Could not determine current branch."));

    if !is_release_branch(&branch, &config.branch) {
        println!("Current branch is '{}', releases are only done from branch '{}'", branch, config.branch);
        println!("No release done from a pull request either.");
        process::exit(0);
    }

    if config.release_mode && ci_env_set() {
        let build_run = Build::from_env()
            .unwrap_or_else(|e| print_exit!("CI mode, but can't check other builds. Error: {:?}", e));

        if !build_run.is_leader() {
            println!("Not the build leader. Nothing to do. Bye.");
            process::exit(0);
        }

        println!("I am the build leader. Waiting for other jobs to finish.");
        match build_run.wait_for_others() {
            Ok(()) => println!("Other jobs finished and succeeded. Doing my work now."),
            Err(travis_after_all::Error::FailedBuilds) => {
                print_exit!("Some builds failed. Stopping here.");
            },
            Err(e) => print_exit!("Waiting for other builds failed Reason: {:?}", e),
        }
    }

    let version = toml_file::read_from_file(&config.repository_path)
        .unwrap_or_else(|err| print_exit!("Reading `Cargo.toml` failed: {:?}", err));

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = git::version_bump_since_latest(&config.repository);
    if write_mode {
        logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));
    } else {
        logger::stdout(format!("Commits analyzed. Bump would be {:?}", bump));
    }
    let new_version = match version_bump(&version, bump) {
        Some(new_version) => new_version.to_string(),
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    if !config.write_mode {
        let changelog = generate_changelog(repository_path, &version, &new_version);
        print_changelog(&changelog);
    } else {
        logger::stdout(format!("New version: {}", new_version));

        toml_file::write_new_version(repository_path, &new_version)
            .unwrap_or_else(|err| print_exit!("Writing `Cargo.toml` failed: {:?}", err));

        write_changelog(&repository_path, &version, &new_version);
        package_crate(&config, &repository_path, &new_version);

        logger::stdout("Creating annotated git tag");
        let tag_message = changelog::generate(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Can't generate changelog: {:?}", err));

        let tag_name = format!("v{}", new_version);
        git::tag(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create git tag: {:?}", err));

        if config.release_mode && config.can_push() {
            push_to_github(&config, &tag_name);
            release_on_github(&config, &tag_message, &tag_name);
            release_on_cratesio(&config);
            println!("{} v{} is released. 🚀🚀🚀", config.repository_name.unwrap(), new_version);
        }
    }
}
<commit_msg>fix: Reorder commands to first commit, then package<commit_after>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

mod logger;
mod toml_file;
mod git;
mod changelog;
mod commit_analyzer;
mod cargo;
mod error;
mod github;
mod config;
mod utils;

extern crate rustc_serialize;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate docopt;
extern crate git2;
extern crate clog;
extern crate hyper;
extern crate hubcaps;
extern crate url;
extern crate travis_after_all;
extern crate env_logger;

use docopt::Docopt;
use commit_analyzer::CommitType;
use config::ConfigBuilder;
use std::process;
use semver::Version;
use std::{env,fs};
use std::path::Path;
use std::error::Error;
use std::thread;
use std::time::Duration;
use travis_after_all::Build;
use utils::user_repo_from_url;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USERAGENT: &'static str = concat!("semantic-rs/", env!("CARGO_PKG_VERSION"));
const USAGE: &'static str = "
semantic.rs 🚀

Usage:
  semantic-rs [options]
  semantic-rs --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  -p PATH, --path=PATH   Specifies the repository path. [default: .]
  -w W, --write=W        Write changes to files (default: yes if CI is set, otherwise no).
  -r R, --release=R      Create release on GitHub and publish on crates.io (only in write mode) [default: yes].
  -b B, --branch=B       The branch on which releases should happen. [default: master].
";

const COMMITTER_ERROR_MESSAGE: &'static str = r"
A release commit needs a committer name and email address.
We tried fetching it from different locations, but couldn't find one.

Committer information is taken from the following environment variables, if set:

GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL

If none is set the normal git config is tried in the following order:

Local repository config
User config
Global config";

macro_rules! print_exit {
    ($fmt:expr) => {{
        logger::stderr($fmt);
        process::exit(1);
    }};
    ($fmt:expr, $($arg:tt)*) => {{
        logger::stderr(format!($fmt, $($arg)*));
        process::exit(1);
    }};
}

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_path: String,
    flag_write: Option<String>,
    flag_version: bool,
    flag_release: String,
    flag_branch: String,
}

fn string_to_bool(answer: &str) -> bool {
    match &answer.to_lowercase()[..] {
        "yes" | "true" | "1" => true,
        _ => false
    }
}

fn version_bump(version: &Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

fn ci_env_set() -> bool {
    env::var("CI").is_ok()
}

fn current_branch(repo: &git2::Repository) -> Option<String> {
    if let Ok(branch) = env::var("TRAVIS_BRANCH") {
        return Some(branch)
    }

    let head = repo.head().expect("No HEAD found for repository");

    if head.is_branch() {
        let short = head.shorthand().expect("No branch name found");
        return Some(short.into());
    }

    None
}

fn is_release_branch(current: &str, release: &str) -> bool {
    if let Ok(pr) = env::var("TRAVIS_PULL_REQUEST") {
        if pr != "false" {
            return false;
        }
    }

    current == release
}

fn push_to_github(config: &config::Config, tag_name: &str) {
    logger::stdout("Pushing new commit and tag");
    git::push(&config, &tag_name)
        .unwrap_or_else(|err| print_exit!("Failed to push git: {:?}", err));

    logger::stdout("Waiting a tiny bit, so GitHub can store the git tag");
    thread::sleep(Duration::from_secs(1));
}

fn release_on_github(config: &config::Config, tag_message: &str, tag_name: &str) {
    if github::can_release(&config) {
        logger::stdout("Creating GitHub release");
        github::release(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create GitHub release: {:?}", err));
    } else {
        logger::stdout("Project not hosted on GitHub. Skipping release step");
    }
}

fn release_on_cratesio(config: &config::Config) {
    logger::stdout("Publishing crate on crates.io");
    if !cargo::publish(&config.repository_path, &config.cargo_token.as_ref().unwrap()) {
        print_exit!("Failed to publish on crates.io");
    }
}

fn generate_changelog(repository_path: &str, version: &Version, new_version: &String) -> String {
    logger::stdout(format!("New version would be: {}", new_version));
    logger::stdout("Would write the following Changelog:");
    match changelog::generate(repository_path, &version.to_string(), new_version) {
        Ok(log) => log,
        Err(err) => {
            logger::stderr(format!("Generating Changelog failed: {:?}", err));
            process::exit(1)
        }
    }
}

fn write_changelog(repository_path: &str, version: &Version, new_version: &str) {
    logger::stdout("Writing Changelog");
    changelog::write(repository_path, &version.to_string(), &new_version)
        .unwrap_or_else(|err| print_exit!("Writing Changelog failed: {:?}", err));
}

fn print_changelog(changelog: &str) {
    logger::stdout("====================================");
    logger::stdout(changelog);
    logger::stdout("====================================");
    logger::stdout("Would create annotated git tag");
}

fn package_crate(config: &config::Config, repository_path: &str, new_version: &str) {
    if config.release_mode {
        logger::stdout("Updating lockfile");
        if !cargo::update_lockfile(repository_path) {
            print_exit!("`cargo fetch` failed. See above for the cargo error message.");
        }
    }

    git::commit_files(&config, &new_version)
        .unwrap_or_else(|err| print_exit!("Committing files failed: {:?}", err));

    logger::stdout("Package crate");
    if !cargo::package(repository_path) {
        print_exit!("`cargo package` failed. See above for the cargo error message.");
    }
}

fn main() {
    env_logger::init().expect("Can't instantiate env logger");

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

    let mut config_builder = ConfigBuilder::new();

    if args.flag_version {
        println!("semantic.rs 🚀 -- v{}", VERSION);
        process::exit(0);
    }

    // If write mode is requested OR denied,
    // adhere to the user's wish,
    // otherwise we decide based on whether we are running in CI.
    let write_mode = match args.flag_write {
        None => ci_env_set(),
        Some(ref flag) => string_to_bool(flag)
    };

    // We can only release, if we are allowed to write
    let release_mode = write_mode && string_to_bool(&args.flag_release);

    config_builder.write(write_mode);
    config_builder.release(release_mode);
    config_builder.branch(args.flag_branch);

    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");
    let path = Path::new(&args.flag_path);
    let path = fs::canonicalize(path)
        .unwrap_or_else(|_| print_exit!("Path does not exist or a component is not a directory"));
    let repository_path = path.to_str()
        .unwrap_or_else(|| print_exit!("Path is not valid unicode"));

    let repo = match git2::Repository::open(repository_path) {
        Ok(repo) => repo,
        Err(e) => {
            logger::stderr(format!("Could not open the git repository: {:?}", e));
            process::exit(1);
        }
    };

    config_builder.repository_path(repository_path.to_owned());

    // extra scope scope to make sure borrow of `repo` is dropped
    {
        let signature = match git::get_signature(&repo) {
            Ok(sig) => sig,
            Err(e) => {
                logger::stderr(format!("Failed to get the committer's name and email address: {}", e.description()));
                logger::stderr(COMMITTER_ERROR_MESSAGE);
                process::exit(1);
            }
        };

        config_builder.signature(signature.to_owned());
    }

    // In case we are in write-mode AND release mode,
    // we will make sure we got all configuration settings
    if write_mode && release_mode {
        let remote_or_none = repo.find_remote("origin");
        match remote_or_none {
            Ok(remote) => {
                let url = remote.url().expect("Remote URL is not valid UTF-8").to_owned();
                let (user, repo_name) = user_repo_from_url(&url)
                    .unwrap_or_else(|e| print_exit!("Could not extract user and repository name from URL: {:?}", e));
                config_builder.user(user);
                config_builder.repository_name(repo_name);

                if github::is_github_url(&url) {
                    let gh_token = env::var("GH_TOKEN")
                        .unwrap_or_else(|err| print_exit!("GH_TOKEN not set: {:?}", err));
                    config_builder.gh_token(gh_token);
                }

                let cargo_token = env::var("CARGO_TOKEN")
                    .unwrap_or_else(|err| print_exit!("CARGO_TOKEN not set: {:?}", err));

                config_builder.cargo_token(cargo_token);
            },
            Err(err) => {
                logger::warn(format!("Could not determine the origin remote url: {:?}", err));
                logger::warn("semantic-rs can't push changes or create a release on GitHub");
            }
        }
    }

    config_builder.repository(repo);
    let config = config_builder.build();

    let branch = current_branch(&config.repository)
        .unwrap_or_else(|| print_exit!("Could not determine current branch."));

    if !is_release_branch(&branch, &config.branch) {
        println!("Current branch is '{}', releases are only done from branch '{}'", branch, config.branch);
        println!("No release done from a pull request either.");
        process::exit(0);
    }

    if config.release_mode && ci_env_set() {
        let build_run = Build::from_env()
            .unwrap_or_else(|e| print_exit!("CI mode, but can't check other builds. Error: {:?}", e));

        if !build_run.is_leader() {
            println!("Not the build leader. Nothing to do. Bye.");
            process::exit(0);
        }

        println!("I am the build leader. Waiting for other jobs to finish.");
        match build_run.wait_for_others() {
            Ok(()) => println!("Other jobs finished and succeeded. Doing my work now."),
            Err(travis_after_all::Error::FailedBuilds) => {
                print_exit!("Some builds failed. Stopping here.");
            },
            Err(e) => print_exit!("Waiting for other builds failed Reason: {:?}", e),
        }
    }

    let version = toml_file::read_from_file(&config.repository_path)
        .unwrap_or_else(|err| print_exit!("Reading `Cargo.toml` failed: {:?}", err));

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = git::version_bump_since_latest(&config.repository);
    if write_mode {
        logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));
    } else {
        logger::stdout(format!("Commits analyzed. Bump would be {:?}", bump));
    }
    let new_version = match version_bump(&version, bump) {
        Some(new_version) => new_version.to_string(),
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    if !config.write_mode {
        let changelog = generate_changelog(repository_path, &version, &new_version);
        print_changelog(&changelog);
    } else {
        logger::stdout(format!("New version: {}", new_version));

        toml_file::write_new_version(repository_path, &new_version)
            .unwrap_or_else(|err| print_exit!("Writing `Cargo.toml` failed: {:?}", err));

        write_changelog(&repository_path, &version, &new_version);
        package_crate(&config, &repository_path, &new_version);

        logger::stdout("Creating annotated git tag");
        let tag_message = changelog::generate(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Can't generate changelog: {:?}", err));

        let tag_name = format!("v{}", new_version);
        git::tag(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create git tag: {:?}", err));

        if config.release_mode && config.can_push() {
            push_to_github(&config, &tag_name);
            release_on_github(&config, &tag_message, &tag_name);
            release_on_cratesio(&config);
            println!("{} v{} is released. 🚀🚀🚀", config.repository_name.unwrap(), new_version);
        }
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{self, Blockchain, Service, GenesisConfig, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding::{self, Field};
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // PERSISTENT DATA // // // // // // // // // //

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

impl Wallet {
    pub fn increase(&mut self, amount: u64) {
        let balance = self.balance() + amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    pub fn decrease(&mut self, amount: u64) {
        let balance = self.balance() - amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }
}

// // // // // // // // // // TRANSACTIONS // // // // // // // // // //

pub const TX_WALLET_ID: u16 = 1;

message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

pub const TX_ISSUE_ID: u16 = 2;

message! {
    struct TxIssue {
        const TYPE = SERVICE_ID;
        const ID = TX_ISSUE_ID;
        const SIZE = 48;

        field pub_key:     &PublicKey  [00 => 32]
        field amount:      u64         [32 => 40]
        field seed:        u64         [40 => 48]
    }
}

pub const TX_TRANSFER_ID: u16 = 3;

message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

// // // // // // // // // // CONTRACTS // // // // // // // // // //

impl Transaction for TxCreateWallet {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        if let None = schema.wallet(self.pub_key()) {
            let wallet = Wallet::new(self.pub_key(), self.name(), 0);
            println!("Create the wallet: {:?}", wallet);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

impl Transaction for TxIssue {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        if let Some(mut wallet) = schema.wallet(self.pub_key()) {
            wallet.increase(self.amount());
            println!("Add funds to wallet: {:?}", wallet);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

impl Transaction for TxTransfer {
    fn verify(&self) -> bool {
        (*self.from() != *self.to()) && self.verify_signature(self.from())
    }

    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(mut sender), Some(mut receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                sender.decrease(amount);
                receiver.increase(amount);
                println!("Transfer between wallets: {:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

#[derive(Clone)]
struct CryptocurrencyApi<T> {
    channel: T,
}

impl<T: TransactionSend + Clone + 'static> Api for CryptocurrencyApi<T> {
    fn wire(&self, router: &mut Router) {

        #[serde(untagged)]
        #[derive(Clone, Serialize, Deserialize)]
        enum TransactionRequest {
            CreateWallet(TxCreateWallet),
            Issue(TxIssue),
            Transfer(TxTransfer),
        }

        impl Into<Box<Transaction>> for TransactionRequest {
            fn into(self) -> Box<Transaction> {
                match self {
                    TransactionRequest::CreateWallet(trans) => Box::new(trans),
                    TransactionRequest::Issue(trans) => Box::new(trans),
                    TransactionRequest::Transfer(trans) => Box::new(trans),
                }
            }
        }

        #[derive(Serialize, Deserialize)]
        struct TransactionResponse {
            tx_hash: Hash,
        }

        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TransactionRequest>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = transaction.into();
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(|e| ApiError::Events(e))?;
                    let json = TransactionResponse { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };
        let route_post = "/v1/wallets/transaction";
        router.post(&route_post, transaction, "transaction");
    }
}

// // // // // // // // // // STORAGE DATA LAYOUT // // // // // // // // // //

pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        let prefix = blockchain::gen_prefix(SERVICE_ID, 0, &());
        MapIndex::new(prefix, self.view)
    }

    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // SERVICE DECLARATION // // // // // // // // // //

pub const SERVICE_ID: u16 = 1;

struct CurrencyService;

impl Service for CurrencyService {
    fn service_name(&self) -> &'static str { "cryptocurrency" }

    fn service_id(&self) -> u16 { SERVICE_ID }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        let trans: Box<Transaction> = match raw.message_type() {
            TX_TRANSFER_ID => Box::new(TxTransfer::from_raw(raw)?),
            TX_ISSUE_ID => Box::new(TxIssue::from_raw(raw)?),
            TX_WALLET_ID => Box::new(TxCreateWallet::from_raw(raw)?),
            _ => {
                return Err(encoding::Error::IncorrectMessageType { message_type: raw.message_type() });
            },
        };
        Ok(trans)
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![
        Box::new(CurrencyService),
    ];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (public_key, secret_key) = exonum::crypto::gen_keypair();

    let peer_address = "0.0.0.0:2000".parse().unwrap();
    let api_address = "0.0.0.0:8000".parse().unwrap();

    let genesis = GenesisConfig::new(vec![public_key].into_iter());

    let api_cfg = NodeApiConfig {
        enable_blockchain_explorer: true,
        public_api_address: Some(api_address),
        private_api_address: None,
    };

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        public_key,
        secret_key,
        genesis,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
    };

    println!("Starting a single node...");
    let mut node = Node::new(blockchain, node_cfg);

    println!("Blockchain in ready for transactions!");
    node.run().unwrap();
}
<commit_msg>Remove TxIssue transaction<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{self, Blockchain, Service, GenesisConfig, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding::{self, Field};
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // PERSISTENT DATA // // // // // // // // // //

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

impl Wallet {
    pub fn increase(&mut self, amount: u64) {
        let balance = self.balance() + amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    pub fn decrease(&mut self, amount: u64) {
        let balance = self.balance() - amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }
}

// // // // // // // // // // TRANSACTIONS // // // // // // // // // //

pub const TX_WALLET_ID: u16 = 1;

message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

pub const TX_TRANSFER_ID: u16 = 3;

message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

// // // // // // // // // // CONTRACTS // // // // // // // // // //

impl Transaction for TxCreateWallet {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        if let None = schema.wallet(self.pub_key()) {
            let wallet = Wallet::new(self.pub_key(), self.name(), 100);
            println!("Create the wallet: {:?}", wallet);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

impl Transaction for TxTransfer {
    fn verify(&self) -> bool {
        (*self.from() != *self.to()) && self.verify_signature(self.from())
    }

    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(mut sender), Some(mut receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                sender.decrease(amount);
                receiver.increase(amount);
                println!("Transfer between wallets: {:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

#[derive(Clone)]
struct CryptocurrencyApi<T> {
    channel: T,
}

impl<T: TransactionSend + Clone + 'static> Api for CryptocurrencyApi<T> {
    fn wire(&self, router: &mut Router) {

        #[serde(untagged)]
        #[derive(Clone, Serialize, Deserialize)]
        enum TransactionRequest {
            CreateWallet(TxCreateWallet),
            Transfer(TxTransfer),
        }

        impl Into<Box<Transaction>> for TransactionRequest {
            fn into(self) -> Box<Transaction> {
                match self {
                    TransactionRequest::CreateWallet(trans) => Box::new(trans),
                    TransactionRequest::Transfer(trans) => Box::new(trans),
                }
            }
        }

        #[derive(Serialize, Deserialize)]
        struct TransactionResponse {
            tx_hash: Hash,
        }

        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TransactionRequest>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = transaction.into();
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(|e| ApiError::Events(e))?;
                    let json = TransactionResponse { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };
        let route_post = "/v1/wallets/transaction";
        router.post(&route_post, transaction, "transaction");
    }
}

// // // // // // // // // // STORAGE DATA LAYOUT // // // // // // // // // //

pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        let prefix = blockchain::gen_prefix(SERVICE_ID, 0, &());
        MapIndex::new(prefix, self.view)
    }

    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // SERVICE DECLARATION // // // // // // // // // //

pub const SERVICE_ID: u16 = 1;

struct CurrencyService;

impl Service for CurrencyService {
    fn service_name(&self) -> &'static str { "cryptocurrency" }

    fn service_id(&self) -> u16 { SERVICE_ID }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        let trans: Box<Transaction> = match raw.message_type() {
            TX_TRANSFER_ID => Box::new(TxTransfer::from_raw(raw)?),
            TX_WALLET_ID => Box::new(TxCreateWallet::from_raw(raw)?),
            _ => {
                return Err(encoding::Error::IncorrectMessageType { message_type: raw.message_type() });
            },
        };
        Ok(trans)
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![
        Box::new(CurrencyService),
    ];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (public_key, secret_key) = exonum::crypto::gen_keypair();

    let peer_address = "0.0.0.0:2000".parse().unwrap();
    let api_address = "0.0.0.0:8000".parse().unwrap();

    let genesis = GenesisConfig::new(vec![public_key].into_iter());

    let api_cfg = NodeApiConfig {
        enable_blockchain_explorer: true,
        public_api_address: Some(api_address),
        private_api_address: None,
    };

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        public_key,
        secret_key,
        genesis,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
    };

    println!("Starting a single node...");
    let mut node = Node::new(blockchain, node_cfg);

    println!("Blockchain in ready for transactions!");
    node.run().unwrap();
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate getopts;
extern crate serde;
extern crate serde_json;
use std::io::Read;
use std::env;
use hyper::Client;
use serde_json::Value;
use getopts::Options;
const KEY: &'static str = "1e940957819058fe3ec7c59d43c09504b400110db7faa0509";
fn main() {
    let wordclient = Client::new();
    let args: Vec<String> = env::args().collect();
    let parser = Options::new();
    let opts = parser.parse(&args[1..]).unwrap();
    for word in opts.free {
        println!("{}:",word.to_uppercase());
        let url = format!("http://api.wordnik.com/v4/word.json/{word}/definitions?api_key={key}",key = KEY, word = word);
        let mut resp = wordclient.get(&url).send().unwrap();
        let mut body = String::new();
        resp.read_to_string(&mut body).unwrap();
        let word: Value = serde_json::from_str(&body).unwrap();
        println!("{}",word.as_array().unwrap()[0].as_object().unwrap().get("text").unwrap().as_string().unwrap());
    }
}
<commit_msg>Added Dict class<commit_after>extern crate hyper;
extern crate getopts;
extern crate serde;
extern crate serde_json;
use std::io::Read;
use std::env;
use hyper::Client;
use serde_json::Value;
use getopts::Options;
const KEY: &'static str = "1e940957819058fe3ec7c59d43c09504b400110db7faa0509";
struct Dict<'a> {
    key: &'a str,
    httpclient: Client
}
impl <'a> Dict <'a> {
    fn new(key: &str) -> Dict {
        Dict {key: key, httpclient: Client::new()}
    }
    fn get_definition(&self,word: &str) -> Vec<Value>  {
        let url = format!("http://api.wordnik.com/v4/word.json/{word}/definitions?api_key={key}",key = self.key, word = word);
        let mut resp = self.httpclient.get(&url).send().expect("Failed to send request");
        let mut body = String::new();
        resp.read_to_string(&mut body).unwrap();
        let word: Value = serde_json::from_str(&body).unwrap();
        word.as_array().unwrap().clone()
    }
}
fn main() {
    let wordclient: Dict = Dict::new(KEY);
    let args: Vec<String> = env::args().collect();
    let parser = Options::new();
    let opts = parser.parse(&args[1..]).unwrap();
    for word in opts.free {
        println!("{}:",word.to_uppercase());
        println!("{}",&wordclient.get_definition("love")[0].as_object().unwrap().get("text").unwrap().as_string().unwrap());
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

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

    // editor source - either a filename or stdin
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    let source = if unsafe { libc::isatty(libc::STDIN_FILENO) == 0 } {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        // FIXME: find a way to do this without unsafe
        //        std::io doesn't allow for this, currently
        buffer_stderr: unsafe { libc::isatty(libc::STDERR_FILENO) == 0 },
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<commit_msg>Fixed assertions<commit_after>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

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

    // editor source - either a filename or stdin
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    let source = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        // FIXME: find a way to do this without unsafe
        //        std::io doesn't allow for this, currently
        buffer_stderr: unsafe { libc::isatty(libc::STDERR_FILENO) == 1 },
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate clap;
extern crate libc;
extern crate multirust;
extern crate rust_install;

extern crate rustc_bisect;

use std::process;

use chrono::{Datelike, NaiveDate};
use clap::{App, AppSettings, Arg};

use rustc_bisect::{Cmd, Error, Result, ToolchainSpec, bisect};

fn run_rust_bisect() -> Result<i32> {
    let matches = App::new("rustc-bisect")
                      .author("Kamal Marhubi <kamal@marhubi.com>")
                      .setting(AppSettings::TrailingVarArg)
                      .arg(Arg::with_name("good")
                               .long("good")
                               .takes_value(true)
                               .value_name("TOOLCHAIN")
                               .required(true))
                      .arg(Arg::with_name("bad")
                               .long("bad")
                               .takes_value(true)
                               .value_name("TOOLCHAIN")
                               .required(true))
                      .arg(Arg::with_name("COMMAND")
                               .multiple(true)
                               .required(true))
                      .get_matches();

    let cfg = try!(multirust::Cfg::from_env(rust_install::notify::SharedNotifyHandler::none()));

    let good = matches.value_of("good").expect("clap didn't respect required arg `good`");
    let good_spec: ToolchainSpec = try!(good.parse());

    let bad = matches.value_of("bad").expect("clap didn't respect required arg `bad`");
    let bad_spec: ToolchainSpec = try!(bad.parse());

    fn get_nightly_date(spec: ToolchainSpec) -> Result<NaiveDate> {
        match spec {
            ToolchainSpec::Nightly(date) => Ok(date),
            _ => Err(Error::from("only nightlies for now")),
        }
    }

    let good_date = try!(get_nightly_date(good_spec));
    let bad_date = try!(get_nightly_date(bad_spec));

    let cmd: Vec<_> = matches.values_of_os("COMMAND").expect("COMMAND").collect();
    let cmd = Cmd::from(&cmd[..]);

    let range = good_date.num_days_from_ce()..bad_date.num_days_from_ce();

    let res = bisect(range, |num_days| {
        let spec = ToolchainSpec::Nightly(NaiveDate::from_num_days_from_ce(num_days));
        let toolchain = cfg.get_toolchain(&spec.to_string(), false).expect("get_toolchain");

        if toolchain.install_from_dist_if_not_installed().is_err() {
            return None;
        }

        let res = cmd.succeeds_with(&toolchain).expect("run command");

        println!("command {} at {}",
                 if res {
                     "succeeded"
                 } else {
                     "failed"
                 },
                 spec);
        Some(!res)
    });

    if let Some(num_days) = res {
        println!("first failing nightly: {}",
                 ToolchainSpec::Nightly(NaiveDate::from_num_days_from_ce(num_days)));
        Ok(libc::EXIT_SUCCESS)
    } else {
        println!("bisect failed");
        Ok(libc::EXIT_FAILURE)
    }
}

fn main() {
    process::exit(run_rust_bisect().expect("something went wrong"));
}
<commit_msg>Comment why we return None on failed download<commit_after>extern crate chrono;
extern crate clap;
extern crate libc;
extern crate multirust;
extern crate rust_install;

extern crate rustc_bisect;

use std::process;

use chrono::{Datelike, NaiveDate};
use clap::{App, AppSettings, Arg};

use rustc_bisect::{Cmd, Error, Result, ToolchainSpec, bisect};

fn run_rust_bisect() -> Result<i32> {
    let matches = App::new("rustc-bisect")
                      .author("Kamal Marhubi <kamal@marhubi.com>")
                      .setting(AppSettings::TrailingVarArg)
                      .arg(Arg::with_name("good")
                               .long("good")
                               .takes_value(true)
                               .value_name("TOOLCHAIN")
                               .required(true))
                      .arg(Arg::with_name("bad")
                               .long("bad")
                               .takes_value(true)
                               .value_name("TOOLCHAIN")
                               .required(true))
                      .arg(Arg::with_name("COMMAND")
                               .multiple(true)
                               .required(true))
                      .get_matches();

    let cfg = try!(multirust::Cfg::from_env(rust_install::notify::SharedNotifyHandler::none()));

    let good = matches.value_of("good").expect("clap didn't respect required arg `good`");
    let good_spec: ToolchainSpec = try!(good.parse());

    let bad = matches.value_of("bad").expect("clap didn't respect required arg `bad`");
    let bad_spec: ToolchainSpec = try!(bad.parse());

    fn get_nightly_date(spec: ToolchainSpec) -> Result<NaiveDate> {
        match spec {
            ToolchainSpec::Nightly(date) => Ok(date),
            _ => Err(Error::from("only nightlies for now")),
        }
    }

    let good_date = try!(get_nightly_date(good_spec));
    let bad_date = try!(get_nightly_date(bad_spec));

    let cmd: Vec<_> = matches.values_of_os("COMMAND").expect("COMMAND").collect();
    let cmd = Cmd::from(&cmd[..]);

    let range = good_date.num_days_from_ce()..bad_date.num_days_from_ce();

    let res = bisect(range, |num_days| {
        let spec = ToolchainSpec::Nightly(NaiveDate::from_num_days_from_ce(num_days));
        let toolchain = cfg.get_toolchain(&spec.to_string(), false).expect("get_toolchain");

        if toolchain.install_from_dist_if_not_installed().is_err() {
            // Assuming this is because the nightly wasn't found.
            // TODO: check the error, and have better reporting.
            return None;
        }

        let res = cmd.succeeds_with(&toolchain).expect("run command");

        println!("command {} at {}",
                 if res {
                     "succeeded"
                 } else {
                     "failed"
                 },
                 spec);
        Some(!res)
    });

    if let Some(num_days) = res {
        println!("first failing nightly: {}",
                 ToolchainSpec::Nightly(NaiveDate::from_num_days_from_ce(num_days)));
        Ok(libc::EXIT_SUCCESS)
    } else {
        println!("bisect failed");
        Ok(libc::EXIT_FAILURE)
    }
}

fn main() {
    process::exit(run_rust_bisect().expect("something went wrong"));
}
<|endoftext|>