<commit_before>#![feature(libc, fs_ext, path_ext, convert, fs, exit_status)]
#![allow(dead_code)]

extern crate crypto;
extern crate libc;

#[macro_use]
extern crate log;
extern crate env_logger;

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::env;
use std::path::Path;
use std::os::unix::fs::PermissionsExt;
use std::io;
use std::io::{Read, Write};
use std::fs::{File, Permissions, create_dir_all,
              set_permissions, PathExt};
use std::process::{Command, Stdio};

const ALL_PERMISSIONS: usize = 0o0777;
const OTHER_EXECUTE: usize = 0o0001;
const OTHER_READ: usize = 0o0004;
const OTHER_RWX: usize = 0o0007;
const GROUP_EXECUTE: usize = 0o0010;
const GROUP_READ: usize = 0o0040;
const GROUP_RWX: usize = 0o0070;
const USER_EXECUTE: usize = 0o0100;
const USER_READ: usize = 0o0400;
const USER_RWX: usize = 0o0700;

trait PermExt2 {
    fn contains(&self, mask: usize) -> bool;
}

impl PermExt2 for Permissions {
    fn contains(&self, mask: usize) -> bool {
        self.mode() & (mask as i32) != 0
    }
}

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust_pnacl_trans";

fn mkdir<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    try!(create_dir_all(&p));
    chmod(p, mode)
}
fn chmod<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    let p = p.as_ref();
    let md = try!(p.metadata());
    let mut perms = md.permissions();
    perms.set_mode(mode as i32);
    set_permissions(p, perms)
}

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

    let args: Vec<String> = env::args()
        .collect();
    let pexe_path = Path::new(&(args[1])[..]);

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let pexe = File::open(&pexe_path);
    if pexe.is_err() {
        panic!("could not open Pexe file!");
    }
    let mut pexe = pexe.unwrap();

    let pexe_filename = Path::new(pexe_path.file_name().unwrap());

    let pexe_stat = pexe.metadata().unwrap();
    let (cache_dir, perms) = if pexe_stat.permissions().contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.permissions().contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.permissions().contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };
    let mut pexe_bin = Vec::new();
    pexe.read_to_end(&mut pexe_bin)
        .unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{:?}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            _ if status.success() => {
                chmod(&nexe_path, perms).unwrap();
            }
            _ => {
                let mut stderr = ::std::io::stderr();
                let mut stdout = ::std::io::stdout();
                (writeln!(&mut stderr, "`{:?}` failed:", cmd)).unwrap();
                stdout.write(output.stdout.as_slice()).unwrap();
                stderr.write(output.stderr.as_slice()).unwrap();
                env::set_exit_status(status.code().unwrap_or(1));
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string());
    match env::var("ALLOW_FILE_ACCESS") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-a".to_string());
        },
        _ => {},
    }
    match env::var("DEBUG_PEXE") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-g".to_string());
        },
        _ => {},
    }

    sel_ldr_args.push("-B".to_string());
    sel_ldr_args.push(irt_core.display().to_string());
    sel_ldr_args.push("-l".to_string());
    sel_ldr_args.push("/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    for arg in &args[2..] {
        sel_ldr_args.push(arg.clone());
    }

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(Stdio::inherit());
    cmd.stderr(Stdio::inherit());
    debug!("sel_ldr cmd line: `{:?}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(status) => {
                    env::set_exit_status(status.code().unwrap_or(1));
                },
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<commit_msg>Print the full nexe path for input to nacl-gdb<commit_after>#![feature(libc, fs_ext, path_ext, convert, fs, exit_status)]
#![allow(dead_code)]

extern crate crypto;
extern crate libc;

#[macro_use]
extern crate log;
extern crate env_logger;

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::env;
use std::path::Path;
use std::os::unix::fs::PermissionsExt;
use std::io;
use std::io::{Read, Write};
use std::fs::{File, Permissions, create_dir_all,
              set_permissions, PathExt};
use std::process::{Command, Stdio};

const ALL_PERMISSIONS: usize = 0o0777;
const OTHER_EXECUTE: usize = 0o0001;
const OTHER_READ: usize = 0o0004;
const OTHER_RWX: usize = 0o0007;
const GROUP_EXECUTE: usize = 0o0010;
const GROUP_READ: usize = 0o0040;
const GROUP_RWX: usize = 0o0070;
const USER_EXECUTE: usize = 0o0100;
const USER_READ: usize = 0o0400;
const USER_RWX: usize = 0o0700;

trait PermExt2 {
    fn contains(&self, mask: usize) -> bool;
}

impl PermExt2 for Permissions {
    fn contains(&self, mask: usize) -> bool {
        self.mode() & (mask as i32) != 0
    }
}

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust_pnacl_trans";

fn mkdir<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    try!(create_dir_all(&p));
    chmod(p, mode)
}
fn chmod<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    let p = p.as_ref();
    let md = try!(p.metadata());
    let mut perms = md.permissions();
    perms.set_mode(mode as i32);
    set_permissions(p, perms)
}

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

    let args: Vec<String> = env::args()
        .collect();
    let pexe_path = Path::new(&(args[1])[..]);

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let pexe = File::open(&pexe_path);
    if pexe.is_err() {
        panic!("could not open Pexe file!");
    }
    let mut pexe = pexe.unwrap();

    let pexe_filename = Path::new(pexe_path.file_name().unwrap());

    let pexe_stat = pexe.metadata().unwrap();
    let (cache_dir, perms) = if pexe_stat.permissions().contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.permissions().contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.permissions().contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };
    let mut pexe_bin = Vec::new();
    pexe.read_to_end(&mut pexe_bin)
        .unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{:?}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            _ if status.success() => {
                chmod(&nexe_path, perms).unwrap();
            }
            _ => {
                let mut stderr = ::std::io::stderr();
                let mut stdout = ::std::io::stdout();
                (writeln!(&mut stderr, "`{:?}` failed:", cmd)).unwrap();
                stdout.write(output.stdout.as_slice()).unwrap();
                stderr.write(output.stderr.as_slice()).unwrap();
                env::set_exit_status(status.code().unwrap_or(1));
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string());
    match env::var("ALLOW_FILE_ACCESS") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-a".to_string());
        },
        _ => {},
    }
    match env::var("DEBUG_PEXE") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-g".to_string());
            println!("note: the nexe path is `{}`", nexe_path.display());
        },
        _ => {},
    }

    sel_ldr_args.push("-B".to_string());
    sel_ldr_args.push(irt_core.display().to_string());
    sel_ldr_args.push("-l".to_string());
    sel_ldr_args.push("/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    for arg in &args[2..] {
        sel_ldr_args.push(arg.clone());
    }

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(Stdio::inherit());
    cmd.stderr(Stdio::inherit());
    debug!("sel_ldr cmd line: `{:?}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(status) => {
                    env::set_exit_status(status.code().unwrap_or(1));
                },
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic::{self, AtomicUsize, Ordering};

/// Indexes used for triple buffer access
/// TODO: Switch to i8 / AtomicI8 once they are stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// A triple buffer, suitable for continuously updating a shared data block
/// in a thread-safe and non-blocking fashion when there is only one producer
/// and one consumer of the data.
struct TripleBuffer<T: Clone> {
    /// Storage for triple-buffered data
    storage: [T; 3],

    /// Index of the write buffer (private to the writer)
    write_idx: TripleBufferIndex,

    /// Index of the back-buffer (shared between reader and writer)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the read buffer (private to the reader)
    read_idx: TripleBufferIndex,

    /// Index of the most up-to-date buffer (written by writer, read by reader)
    last_idx: AtomicTripleBufferIndex,
}

// Implementation of the triple buffer
impl<T: Clone> TripleBuffer<T> {
    /// Create a new triple buffer with some initial data value
    fn new(initial: T) -> Self {
        TripleBuffer {
            storage: [initial.clone(), initial.clone(), initial.clone()],
            write_idx: 0,
            back_idx: AtomicTripleBufferIndex::new(1),
            read_idx: 2,
            last_idx: AtomicTripleBufferIndex::new(2),
        }
    }

    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Select a write buffer that we have exclusive access to
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        self.storage[active_idx] = value;

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = self.back_idx.swap(active_idx, Ordering::Relaxed);

        // Allow the reader to detect and synchronize with this update
        self.last_idx.store(active_idx, Ordering::Release);
    }

    /// Access the latest value from the triple buffer
    fn read(&mut self) -> &T {
        // Check which buffer was last written to
        let last_idx = self.last_idx.load(Ordering::Relaxed);

        // Update the read buffer if an update has occured since the last read
        if self.read_idx != last_idx {
            // Synchronize with the writer's updates
            atomic::fence(Ordering::Acquire);

            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = self.back_idx.swap(self.read_idx, Ordering::Relaxed);
        }

        // Access data from the current read buffer
        &self.storage[self.read_idx]
    }
}

/// Unit tests for triple buffers
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Cache atomic indices for convenience
        let back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf.last_idx.load(::Ordering::Relaxed);

        // Write, read and back-buffer indexes must be in range
        assert!(index_in_range(buf.read_idx));
        assert!(index_in_range(buf.write_idx));
        assert!(index_in_range(back_idx));

        // Write, read and back-buffer indexes must be distinct
        assert!(buf.read_idx != buf.write_idx);
        assert!(buf.read_idx != back_idx);
        assert!(buf.write_idx != back_idx);

        // Read buffer must be properly initialized
        assert!(buf.storage[buf.read_idx] == 42);

        // Last-written index must initially point to read buffer
        assert_eq!(buf.read_idx, last_idx);
    }

    /// Range check for triple buffer indexes
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.read());

    buf.write("World!");
    println!("New value is {}", buf.read())
}
<commit_msg>Added write test<commit_after>use std::sync::atomic::{self, AtomicUsize, Ordering};

/// Indexes used for triple buffer access
/// TODO: Switch to i8 / AtomicI8 once they are stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// A triple buffer, suitable for continuously updating a shared data block
/// in a thread-safe and non-blocking fashion when there is only one producer
/// and one consumer of the data.
struct TripleBuffer<T: Clone> {
    /// Storage for triple-buffered data
    storage: [T; 3],

    /// Index of the write buffer (private to the writer)
    write_idx: TripleBufferIndex,

    /// Index of the back-buffer (shared between reader and writer)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the read buffer (private to the reader)
    read_idx: TripleBufferIndex,

    /// Index of the most up-to-date buffer (written by writer, read by reader)
    last_idx: AtomicTripleBufferIndex,
}

// Implementation of the triple buffer
impl<T: Clone> TripleBuffer<T> {
    /// Create a new triple buffer with some initial data value
    fn new(initial: T) -> Self {
        TripleBuffer {
            storage: [initial.clone(), initial.clone(), initial.clone()],
            write_idx: 0,
            back_idx: AtomicTripleBufferIndex::new(1),
            read_idx: 2,
            last_idx: AtomicTripleBufferIndex::new(2),
        }
    }

    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Select a write buffer that we have exclusive access to
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        self.storage[active_idx] = value;

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = self.back_idx.swap(active_idx, Ordering::Relaxed);

        // Allow the reader to detect and synchronize with this update
        self.last_idx.store(active_idx, Ordering::Release);
    }

    /// Access the latest value from the triple buffer
    fn read(&mut self) -> &T {
        // Check which buffer was last written to
        let last_idx = self.last_idx.load(Ordering::Relaxed);

        // Update the read buffer if an update has occured since the last read
        if self.read_idx != last_idx {
            // Synchronize with the writer's updates
            atomic::fence(Ordering::Acquire);

            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = self.back_idx.swap(self.read_idx, Ordering::Relaxed);
        }

        // Access data from the current read buffer
        &self.storage[self.read_idx]
    }
}

/// Unit tests for triple buffers
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Cache atomic indices for convenience
        let back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf.last_idx.load(::Ordering::Relaxed);

        // Write, read and back-buffer indexes must be in range
        assert!(index_in_range(buf.read_idx));
        assert!(index_in_range(buf.write_idx));
        assert!(index_in_range(back_idx));

        // Write, read and back-buffer indexes must be distinct
        assert!(buf.read_idx != buf.write_idx);
        assert!(buf.read_idx != back_idx);
        assert!(buf.write_idx != back_idx);

        // Read buffer must be properly initialized
        assert!(buf.storage[buf.read_idx] == 42);

        // Last-written index must initially point to read buffer
        assert_eq!(last_idx, buf.read_idx);
    }

    /// Test that (sequentially) writing to a triple buffer works
    #[test]
    fn test_seq_write() {
        // Let's create a triple buffer
        let mut buf = ::TripleBuffer::new(false);

        // Back up initial state
        let init_storage = buf.storage.clone();
        let init_write_idx = buf.write_idx;
        let init_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let init_read_idx = buf.read_idx;

        // Perform a write
        buf.write(true);

        // Only the write buffer should have changed
        let mut expected_storage = init_storage.clone();
        expected_storage[init_write_idx] = true;
        assert_eq!(buf.storage, expected_storage);

        // Write index should point to the former back buffer
        assert_eq!(buf.write_idx, init_back_idx);

        // Back index should point to the former write buffer
        let new_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        assert_eq!(new_back_idx, init_write_idx);

        // Read index should be unchanged
        assert_eq!(buf.read_idx, init_read_idx);

        // Last index should point to the newly written buffer
        let new_last_idx = buf.last_idx.load(::Ordering::Relaxed);
        assert_eq!(new_last_idx, init_write_idx);
    }

    // TODO: Check that (sequentially) reading from a triple buffer works
    // TODO: Check that concurrent reads and writes work

    /// Range check for triple buffer indexes
    #[allow(unused_comparisons)]
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.read());

    buf.write("World!");
    println!("New value is {}", buf.read())
}
<|endoftext|>


<commit_before>extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;

use std::path::Path;
use glutin_window::GlutinWindow;
use opengl_graphics::{GlGraphics, OpenGL};
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::{Event, Events, RenderEvent, EventLoop};
use piston::input::{Button, Input, Motion, MouseButton};
use piston::window::WindowSettings;
use graphics::{Context, Ellipse, Rectangle, Transformed};

mod color {
    pub const VIOLET: [f32; 4] = [0.6, 0.0, 1.0, 1.0];
    pub const BLACK:  [f32; 4] = [0.0, 0.0, 0.0, 1.0];
    pub const WHITE:  [f32; 4] = [1.0, 1.0, 1.0, 1.0];
    pub const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
}

struct Vector {
    x: f64,
    y: f64
}

struct Ball {
    center: Vector,
    speed: Vector,
    radius: f64
}

impl Ball {
    fn new(center: Vector) -> Ball {
        Ball {
            center: center,
            speed: Vector {
                x: 500.0,
                y: 200.0
            },
            radius: 10.0
        }
    }

    fn update(&mut self, dt: f64) {
        self.center.x += self.speed.x * dt;
        self.center.y += self.speed.y * dt;
    }

    fn reset(&mut self, window_width: f64, window_height: f64) {
        // recenter the ball
        self.center.x = window_width / 2.0;
        self.center.y = window_height / 2.0;

        // change up the speed
        self.speed.x = -self.speed.x;
        self.speed.y = -self.speed.y;
    }
}

struct Game {
    ball: Ball,

    window_width: f64,
    window_height: f64,

    paddle_width: f64,
    paddle_height: f64,

    // y-coordinate of center of player 1 (left) paddle
    paddle_1_y: f64,
    // y-coordinate of mouse
    mouse_y: f64,

    paddle_2_y: f64,

    // player 1's score
    score_1: u8,
    score_2: u8,
    showing_win_screen: bool,

    // the score needed to win a game
    winning_score: u8,

    font: GlyphCache<'static>
}

impl Game {
    // constructs a new Game object
    fn new(width: f64, height: f64) -> Game {
        let ball = Ball::new(
            // ball starts in the center of the window
            Vector {
                x: width / 2.0,
                y: height / 2.0
            }
        );

        Game {
            ball: ball,

            window_width: width,
            window_height: height,

            paddle_width: 10.0,
            paddle_height: 100.0,

            // start the paddles vertically centered
            paddle_1_y: height / 2.0,
            mouse_y: height / 2.0,

            paddle_2_y: height / 2.0,

            score_1: 0,
            score_2: 0,
            showing_win_screen: false,

            winning_score: 5,

            font: GlyphCache::new(&Path::new("resources/FiraMono-Bold.ttf")).unwrap()
        }
    }

    // called after a game has been finished and the user has clicked for a new game
    fn reset(&mut self) {
        self.score_1 = 0;
        self.score_2 = 0;
        self.showing_win_screen = false;

        self.ball.reset(self.window_width, self.window_height);
    }

    // called when a player has scored
    fn scored(&mut self, player: u8) {
        // increment the appropriate score
        if player == 2 {
            self.score_2 += 1;
        } else {
            self.score_1 += 1;
        }

        // check if the game is done
        if self.score_1 == self.winning_score || self.score_2 == self.winning_score {
            self.showing_win_screen = true;
        }

        self.ball.reset(self.window_width, self.window_height);
    }

    fn render(&mut self, c: Context, gl: &mut GlGraphics) {
        // clear everything
        graphics::clear(color::BLACK, gl);

        if self.showing_win_screen {
            // present the game over screen
            let mut text = graphics::Text::new(22);
            text.color = color::ORANGE;
            let player_number = if self.score_1 == self.winning_score {
                1
            } else {
                2
            };
            text.draw(&format!("Player {} wins! Click to continue", player_number),
                &mut self.font,
                &c.draw_state,
                c.trans(self.window_width / 2.0 - 200.0, self.window_height / 2.0).transform,
                gl);

            return;
        }

        // draw the ball
        let diameter = self.ball.radius * 2.0;
        Ellipse::new(color::VIOLET).draw(
            [self.ball.center.x - self.ball.radius, self.ball.center.y - self.ball.radius, diameter, diameter],
            &c.draw_state, c.transform, gl);

        // draw the left paddle
        Rectangle::new(color::WHITE).draw(
            [0.0, self.paddle_1_y - self.paddle_height / 2.0, self.paddle_width, self.paddle_height],
            &c.draw_state, c.transform, gl);

        // draw the right paddle
        Rectangle::new(color::WHITE).draw(
            [self.window_width - self.paddle_width, self.paddle_2_y - self.paddle_height / 2.0, self.paddle_width, self.paddle_height],
            &c.draw_state, c.transform, gl);

        // draw the score
        let mut text = graphics::Text::new(22);
        text.color = color::ORANGE;
        text.draw(&format!("Score: {}", self.score_1),
                  &mut self.font,
                  &c.draw_state,
                  c.trans(10.0, 20.0).transform,
                  gl);

        text.draw(&format!("Score: {}", self.score_2),
                  &mut self.font,
                  &c.draw_state,
                  c.trans(self.window_width / 2.0, 20.0).transform,
                  gl);
    }

    fn update(&mut self, dt: f64) {
        if self.showing_win_screen {
            // do nothing if the game is over
            return;
        }

        // move the ball
        self.ball.update(dt);

        // move the paddle
        self.paddle_1_y = self.mouse_y;

        // right paddle AI
        if self.ball.center.y > self.paddle_2_y {
            // if the ball is below our center, move down
            self.paddle_2_y += 200.0 * dt;
        } else if self.ball.center.y < self.paddle_2_y {
            // if the ball is above our center, move up
            self.paddle_2_y -= 200.0 * dt;
        }

        // check if the ball is touching the left paddle
        if self.ball.center.x - self.ball.radius < self.paddle_width
            && self.ball.center.y >= self.paddle_1_y - self.paddle_height / 2.0
            && self.ball.center.y <= self.paddle_1_y + self.paddle_height / 2.0 {

            // reflect the ball
            self.ball.speed.x = -self.ball.speed.x;
            let delta_y = self.ball.center.y - self.paddle_1_y;
            self.ball.speed.y = delta_y * 8.0;

        } else if self.ball.center.x - self.ball.radius <= 0.0 {
            // ball has hit the left side
            self.scored(2);
        }

        // check if the ball is touching the right paddle
        if self.ball.center.x + self.ball.radius > self.window_width - self.paddle_width
            && self.ball.center.y >= self.paddle_2_y - self.paddle_height / 2.0
            && self.ball.center.y <= self.paddle_2_y + self.paddle_height / 2.0 {

            // reflect the ball
            self.ball.speed.x = -self.ball.speed.x;
            let delta_y = self.ball.center.y - self.paddle_2_y;
            self.ball.speed.y = delta_y * 8.0;

        } else if self.ball.center.x + self.ball.radius >= self.window_width {
            // ball has hit the right side
            self.scored(1);
        }

        if self.ball.center.y + self.ball.radius >= self.window_height || self.ball.center.y - self.ball.radius <= 0.0 {
            // ball has hit the top or bottom
            self.ball.speed.y = -self.ball.speed.y;
        }
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let width = 1024;
    let height = 600;
    let window: GlutinWindow =
        WindowSettings::new("Pong", [width, height])
            .exit_on_esc(true)
            .opengl(opengl)
            .samples(8) // TODO: Figure out the purpose of this line
            .vsync(true)
            .into();

    let mut gl = GlGraphics::new(opengl);

    let mut game = Game::new(width as f64, height as f64);

    for e in window.events().ups(60).max_fps(60) {
        match e {
            Event::Input(Input::Release(Button::Mouse(mouse))) => {
                if game.showing_win_screen {
                    match mouse {
                        MouseButton::Left => game.reset(),
                        _ => ()
                    }
                }
            }

            Event::Input(Input::Move(Motion::MouseCursor(_, y))) => {
                game.mouse_y = y;
            },

            Event::Render(args) => {
                gl.draw(args.viewport(), |c, g| game.render(c, g));
            }

            Event::Update(args) => {
                game.update(args.dt);
            }

            _ => {}
        }
    }
}

<commit_msg>Add a comment to ball.update(), remove TODO<commit_after>extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;

use std::path::Path;
use glutin_window::GlutinWindow;
use opengl_graphics::{GlGraphics, OpenGL};
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::{Event, Events, RenderEvent, EventLoop};
use piston::input::{Button, Input, Motion, MouseButton};
use piston::window::WindowSettings;
use graphics::{Context, Ellipse, Rectangle, Transformed};

mod color {
    pub const VIOLET: [f32; 4] = [0.6, 0.0, 1.0, 1.0];
    pub const BLACK:  [f32; 4] = [0.0, 0.0, 0.0, 1.0];
    pub const WHITE:  [f32; 4] = [1.0, 1.0, 1.0, 1.0];
    pub const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
}

struct Vector {
    x: f64,
    y: f64
}

struct Ball {
    center: Vector,
    speed: Vector,
    radius: f64
}

impl Ball {
    fn new(center: Vector) -> Ball {
        Ball {
            center: center,
            speed: Vector {
                x: 500.0,
                y: 200.0
            },
            radius: 10.0
        }
    }

    fn update(&mut self, dt: f64) {
        // move the ball according to its current speed and the dt parameter
        self.center.x += self.speed.x * dt;
        self.center.y += self.speed.y * dt;
    }

    fn reset(&mut self, window_width: f64, window_height: f64) {
        // recenter the ball
        self.center.x = window_width / 2.0;
        self.center.y = window_height / 2.0;

        // change up the speed
        self.speed.x = -self.speed.x;
        self.speed.y = -self.speed.y;
    }
}

struct Game {
    ball: Ball,

    window_width: f64,
    window_height: f64,

    paddle_width: f64,
    paddle_height: f64,

    // y-coordinate of center of player 1 (left) paddle
    paddle_1_y: f64,
    // y-coordinate of mouse
    mouse_y: f64,

    paddle_2_y: f64,

    // player 1's score
    score_1: u8,
    score_2: u8,
    showing_win_screen: bool,

    // the score needed to win a game
    winning_score: u8,

    font: GlyphCache<'static>
}

impl Game {
    // constructs a new Game object
    fn new(width: f64, height: f64) -> Game {
        let ball = Ball::new(
            // ball starts in the center of the window
            Vector {
                x: width / 2.0,
                y: height / 2.0
            }
        );

        Game {
            ball: ball,

            window_width: width,
            window_height: height,

            paddle_width: 10.0,
            paddle_height: 100.0,

            // start the paddles vertically centered
            paddle_1_y: height / 2.0,
            mouse_y: height / 2.0,

            paddle_2_y: height / 2.0,

            score_1: 0,
            score_2: 0,
            showing_win_screen: false,

            winning_score: 5,

            font: GlyphCache::new(&Path::new("resources/FiraMono-Bold.ttf")).unwrap()
        }
    }

    // called after a game has been finished and the user has clicked for a new game
    fn reset(&mut self) {
        self.score_1 = 0;
        self.score_2 = 0;
        self.showing_win_screen = false;

        self.ball.reset(self.window_width, self.window_height);
    }

    // called when a player has scored
    fn scored(&mut self, player: u8) {
        // increment the appropriate score
        if player == 2 {
            self.score_2 += 1;
        } else {
            self.score_1 += 1;
        }

        // check if the game is done
        if self.score_1 == self.winning_score || self.score_2 == self.winning_score {
            self.showing_win_screen = true;
        }

        self.ball.reset(self.window_width, self.window_height);
    }

    fn render(&mut self, c: Context, gl: &mut GlGraphics) {
        // clear everything
        graphics::clear(color::BLACK, gl);

        if self.showing_win_screen {
            // present the game over screen
            let mut text = graphics::Text::new(22);
            text.color = color::ORANGE;
            let player_number = if self.score_1 == self.winning_score {
                1
            } else {
                2
            };
            text.draw(&format!("Player {} wins! Click to continue", player_number),
                &mut self.font,
                &c.draw_state,
                c.trans(self.window_width / 2.0 - 200.0, self.window_height / 2.0).transform,
                gl);

            return;
        }

        // draw the ball
        let diameter = self.ball.radius * 2.0;
        Ellipse::new(color::VIOLET).draw(
            [self.ball.center.x - self.ball.radius, self.ball.center.y - self.ball.radius, diameter, diameter],
            &c.draw_state, c.transform, gl);

        // draw the left paddle
        Rectangle::new(color::WHITE).draw(
            [0.0, self.paddle_1_y - self.paddle_height / 2.0, self.paddle_width, self.paddle_height],
            &c.draw_state, c.transform, gl);

        // draw the right paddle
        Rectangle::new(color::WHITE).draw(
            [self.window_width - self.paddle_width, self.paddle_2_y - self.paddle_height / 2.0, self.paddle_width, self.paddle_height],
            &c.draw_state, c.transform, gl);

        // draw the score
        let mut text = graphics::Text::new(22);
        text.color = color::ORANGE;
        text.draw(&format!("Score: {}", self.score_1),
                  &mut self.font,
                  &c.draw_state,
                  c.trans(10.0, 20.0).transform,
                  gl);

        text.draw(&format!("Score: {}", self.score_2),
                  &mut self.font,
                  &c.draw_state,
                  c.trans(self.window_width / 2.0, 20.0).transform,
                  gl);
    }

    fn update(&mut self, dt: f64) {
        if self.showing_win_screen {
            // do nothing if the game is over
            return;
        }

        // move the ball
        self.ball.update(dt);

        // move the paddle
        self.paddle_1_y = self.mouse_y;

        // right paddle AI
        if self.ball.center.y > self.paddle_2_y {
            // if the ball is below our center, move down
            self.paddle_2_y += 200.0 * dt;
        } else if self.ball.center.y < self.paddle_2_y {
            // if the ball is above our center, move up
            self.paddle_2_y -= 200.0 * dt;
        }

        // check if the ball is touching the left paddle
        if self.ball.center.x - self.ball.radius < self.paddle_width
            && self.ball.center.y >= self.paddle_1_y - self.paddle_height / 2.0
            && self.ball.center.y <= self.paddle_1_y + self.paddle_height / 2.0 {

            // reflect the ball
            self.ball.speed.x = -self.ball.speed.x;
            let delta_y = self.ball.center.y - self.paddle_1_y;
            self.ball.speed.y = delta_y * 8.0;

        } else if self.ball.center.x - self.ball.radius <= 0.0 {
            // ball has hit the left side
            self.scored(2);
        }

        // check if the ball is touching the right paddle
        if self.ball.center.x + self.ball.radius > self.window_width - self.paddle_width
            && self.ball.center.y >= self.paddle_2_y - self.paddle_height / 2.0
            && self.ball.center.y <= self.paddle_2_y + self.paddle_height / 2.0 {

            // reflect the ball
            self.ball.speed.x = -self.ball.speed.x;
            let delta_y = self.ball.center.y - self.paddle_2_y;
            self.ball.speed.y = delta_y * 8.0;

        } else if self.ball.center.x + self.ball.radius >= self.window_width {
            // ball has hit the right side
            self.scored(1);
        }

        if self.ball.center.y + self.ball.radius >= self.window_height || self.ball.center.y - self.ball.radius <= 0.0 {
            // ball has hit the top or bottom
            self.ball.speed.y = -self.ball.speed.y;
        }
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let width = 1024;
    let height = 600;
    let window: GlutinWindow =
        WindowSettings::new("Pong", [width, height])
            .exit_on_esc(true)
            .opengl(opengl)
            .samples(8)
            .vsync(true)
            .into();

    let mut gl = GlGraphics::new(opengl);

    let mut game = Game::new(width as f64, height as f64);

    for e in window.events().ups(60).max_fps(60) {
        match e {
            Event::Input(Input::Release(Button::Mouse(mouse))) => {
                if game.showing_win_screen {
                    match mouse {
                        MouseButton::Left => game.reset(),
                        _ => ()
                    }
                }
            }

            Event::Input(Input::Move(Motion::MouseCursor(_, y))) => {
                game.mouse_y = y;
            },

            Event::Render(args) => {
                gl.draw(args.viewport(), |c, g| game.render(c, g));
            }

            Event::Update(args) => {
                game.update(args.dt);
            }

            _ => {}
        }
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

use glium::{DisplayBuild, Surface};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Point {
    position: (f32, f32)
}

implement_vertex!(Point, position);

/// The four corners of OpenGL screen space.
const VERTICES: [Point; 4] = [
    Point { position: (  1.0,  1.0 ) },
    Point { position: ( -1.0,  1.0 ) },
    Point { position: ( -1.0, -1.0 ) },
    Point { position: (  1.0, -1.0 ) },
];

/// Two triangles arranged as a rectangle covering OpenGL screen space.
/// All the real work happens in the fragment shader, so we just want to
/// run the shader on every pixel.
const INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3
];

fn main() {
    let mut builder = glium::glutin::WindowBuilder::new();
    builder.opengl.vsync = true;

    let display = builder.build_glium()
        .expect("failed to build glium window");

    let positions = glium::VertexBuffer::new(&display, &VERTICES)
        .expect("building positions");
    let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &INDICES)
        .expect("building indices");

    let program = glium::Program::from_source(&display,
                                              &include_str!("julia.vert"),
                                              &include_str!("julia.frag"),
                                              None)
        .expect("building program");

    let mut dimensions = display.get_framebuffer_dimensions();
    let mut aspect = dimensions.0 as f32 / dimensions.1 as f32;
    let mut c = [ 0.0, 0.0f32 ];

    loop {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);

        let params = Default::default();
        target.draw(&positions, &indices, &program,
                    &uniform! {
                        screen_to_complex: if aspect < 1.0 {
                            [ 2.0, 2.0 / aspect ]
                        } else {
                            [ 2.0 * aspect, 2.0 ]
                        },
                        c: c },
                    &params)
            .expect("target.draw");
        target.finish().expect("target.finish");

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::Resized(w, h) => {
                    dimensions = (w, h);
                    aspect = dimensions.0 as f32 / dimensions.1 as f32;
                }
                glium::glutin::Event::MouseMoved(x,y) => {
                    // Map pixels to complex coordinates, keeping the circle of radius
                    // two centered at the origin in the middle of the image.
                    if dimensions.0 > dimensions.1 {
                        // Window is wider than it is high.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0 * aspect;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0;
                    } else {
                        // Window is higher than it is wide.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0 / aspect;
                    }
                },
                _ => ()
            }
        }
    }
}
<commit_msg>Reload shaders as they change<commit_after>#[macro_use]
extern crate glium;

use std::io;
use std::io::prelude::*;
use std::fs::File;

use glium::{DisplayBuild, Surface, Program};
use glium::backend::Facade;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Point {
    position: (f32, f32)
}

implement_vertex!(Point, position);

/// The four corners of OpenGL screen space.
const VERTICES: [Point; 4] = [
    Point { position: (  1.0,  1.0 ) },
    Point { position: ( -1.0,  1.0 ) },
    Point { position: ( -1.0, -1.0 ) },
    Point { position: (  1.0, -1.0 ) },
];

/// Two triangles arranged as a rectangle covering OpenGL screen space.
/// All the real work happens in the fragment shader, so we just want to
/// run the shader on every pixel.
const INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3
];

fn main() {
    let mut builder = glium::glutin::WindowBuilder::new();
    builder.opengl.vsync = true;

    let display = builder.build_glium()
        .expect("failed to build glium window");

    let positions = glium::VertexBuffer::new(&display, &VERTICES)
        .expect("building positions");
    let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &INDICES)
        .expect("building indices");

    let mut dimensions = display.get_framebuffer_dimensions();
    let mut aspect = dimensions.0 as f32 / dimensions.1 as f32;
    let mut c = [ 0.0, 0.0f32 ];

    let mut program = load_shader_program(&display).unwrap();

    loop {
        if let Ok(p) = load_shader_program(&display) {
            program = p;
        }

        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);

        let params = Default::default();
        target.draw(&positions, &indices, &program,
                    &uniform! {
                        screen_to_complex: if aspect < 1.0 {
                            [ 2.0, 2.0 / aspect ]
                        } else {
                            [ 2.0 * aspect, 2.0 ]
                        },
                        c: c },
                    &params)
            .expect("target.draw");
        target.finish().expect("target.finish");

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::Resized(w, h) => {
                    dimensions = (w, h);
                    aspect = dimensions.0 as f32 / dimensions.1 as f32;
                }
                glium::glutin::Event::MouseMoved(x,y) => {
                    // Map pixels to complex coordinates, keeping the circle of radius
                    // two centered at the origin in the middle of the image.
                    if dimensions.0 > dimensions.1 {
                        // Window is wider than it is high.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0 * aspect;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0;
                    } else {
                        // Window is higher than it is wide.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0 / aspect;
                    }
                },
                _ => ()
            }
        }
    }
}

#[derive(Debug)]
struct ShaderError;

impl From<std::io::Error> for ShaderError {
    fn from(e: io::Error) -> ShaderError {
        ShaderError
    }
}

fn read_file(path: &str) -> io::Result<String> {
    let mut s = String::new();
    let mut f = try!(File::open(path));
    try!(f.read_to_string(&mut s));
    Ok(s)
}

fn load_shader_program<F: Facade>(display: &F) -> Result<Program, ShaderError> {
    let vert_shader = try!(read_file("src/julia.vert"));
    let frag_shader = try!(read_file("src/julia.frag"));
    if let Ok(p) = glium::Program::from_source(display, &vert_shader, &frag_shader, None) {
        Ok(p)
    } else {
        Err(ShaderError)
    }
}
<|endoftext|>


<commit_before>
extern crate mprovision;
extern crate clap;

use std::fs;
use clap::{Arg, App, AppSettings, SubCommand};

fn main() {
    let count_subcommand = SubCommand::with_name("count")
        .about("Counts provisioning profiles in a directory.")
        .arg(Arg::with_name("DIRECTORY")
            .short("d")
            .long("directory")
            .help("Directory where to count provisioning profiles.")
            .required(false)
            .takes_value(true));

    let matches = App::new("mprovision")
        .setting(AppSettings::SubcommandRequired)
        .version("0.1.0")
        .about("A tool that helps iOS developers to manage mobileprovision files.")
        .subcommand(count_subcommand)
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("count") {
        handle_count_subcommand(matches)
    }
}

fn handle_count_subcommand(matches: &clap::ArgMatches) {

    fn show(result: mprovision::Result<Box<Iterator<Item=fs::DirEntry>>>) {
        match result {
            Ok(files) => println!("Found {} files.", files.count()),
            Err(err) => println!("Error: {}", err),
        }
    }

    if let Some(directory) = matches.value_of("DIRECTORY") {
        show(mprovision::files(directory));
    } else {
        match mprovision::directory() {
            Ok(directory) => show(mprovision::files(directory)),
            Err(err) => println!("Error: {}", err),
        }
    }
}
<commit_msg>Remove unnecessary arg name for 'count' subcommand.<commit_after>
extern crate mprovision;
extern crate clap;

use std::fs;
use clap::{Arg, App, AppSettings, SubCommand};

fn main() {
    let count_subcommand = SubCommand::with_name("count")
        .about("Counts provisioning profiles in a directory.")
        .arg(Arg::with_name("DIRECTORY")
            .help("Directory where to count provisioning profiles.")
            .required(false));

    let matches = App::new("mprovision")
        .setting(AppSettings::SubcommandRequired)
        .version("0.1.0")
        .about("A tool that helps iOS developers to manage mobileprovision files.")
        .subcommand(count_subcommand)
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("count") {
        handle_count_subcommand(matches)
    }
}

fn handle_count_subcommand(matches: &clap::ArgMatches) {

    fn show(result: mprovision::Result<Box<Iterator<Item=fs::DirEntry>>>) {
        match result {
            Ok(files) => println!("Found {} files.", files.count()),
            Err(err) => println!("Error: {}", err),
        }
    }

    if let Some(directory) = matches.value_of("DIRECTORY") {
        show(mprovision::files(directory));
    } else {
        match mprovision::directory() {
            Ok(directory) => show(mprovision::files(directory)),
            Err(err) => println!("Error: {}", err),
        }
    }
}
<|endoftext|>


<commit_before>extern crate yaml_rust;
extern crate regex;

use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool
}

fn to_hex(bytes: &[u8]) -> String {
  let mut count = 0;
  let mut result = String::with_capacity(67);
  let mut dotline = String::with_capacity(18);

  for byte in bytes.iter() {
    if count != 0 && count%8 == 0 {
      result.push(' ');
      if count%16 == 0 {
        dotline.push('\n');
        result.push_str(&dotline);
        result.reserve(67);
        dotline.truncate(0);
      }
      else { dotline.push(' '); }
    }
    result.push_str(&format!("{:02X} ", byte));
    if *byte > 31 && *byte < 127 { dotline.push(*byte as char) }
    else if *byte == 0 { dotline.push('-'); }
    else { dotline.push('.'); }
    count += 1;
  }
  while count%16 != 0 {
    if count%8 == 0 { result.push(' '); }
    result.push_str("   ");
    count += 1;
  }
  if dotline.len() != 0 { result.push_str(&dotline); }
  result
}

fn main() {
  println!("Portlurker v{}", VERSION);
  println!("{}", AUTHORS);

  let mut app = App { print_ascii: false, print_binary: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]"),
    ("SMB2 COMMAND NEGOTIATE", r"^\x00...\xfeSMB........\x00\x00"),
    ("SMB2 NT_STATUS Success", r"^\x00...\xfeSMB....[\x00-\x0f]"),
    ("SMB2 NT_STATUS Information", r"^\x00...\xfeSMB....[\x40-\x4f]"),
    ("SMB2 NT_STATUS Warning", r"^\x00...\xfeSMB....[\x80-\x8f]"),
    ("SMB2 NT_STATUS Error", r"^\x00...\xfeSMB....[\xc0-\xcf]"),
    ("MS-TDS PRELOGIN Request", r"^\x12\x01\x00.\x00\x00"),
    ("MS-TDS LOGIN Request", r"^\x10\x01\x00.\x00\x00"),
    ("SOCKS5 NOAUTH Request", r"^\x05\x01\x00$"),
    ("SOCKS5 NOAUTH,USER/PASS Request", r"^\x05\x02\x00\x02$")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ASCII);
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary in hexadecimal");
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  println!("Starting listeners on the following ports:");

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = match res {
            Ok(stream) => stream,
            Err(e) => { println!("ACCEPT ERROR TCP {}: {}", portno, e.to_string()); continue; }
          };
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);
          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("WRITE TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut mbfound = false;
                  let mut mbstring = String::new();
                  let mut start = 0;
                  for i in 0..c {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        if (i-start == 1) {
                          if (start > 0) && (buf[start-1] == 0) {
                            mbstring.push(buf[i-1] as char);
                            if !mbfound { mbfound = true; }
                          }
                        }
                        else { printables.push(&buf[start..i]); }
                        found = false;
                      }
                      else if mbfound {
                        mbstring.push('\n');
                        mbfound = false;
                      }
                    }
                  }
                  if found { printables.push(&buf[start..c]); }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ASCII", c); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("^ Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                    for line in mbstring.lines() {
                      if line.len() > 3 { println!("% {}", line); }
                    }
                    if app.print_binary {
                      let hex = to_hex(&buf[..c]);
                      for line in hex.lines() { println!(". {}", line); }
                    }
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("READ TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<commit_msg>Fixed missing quote, included bart's latest pattern matches for SOCKS<commit_after>extern crate yaml_rust;
extern crate regex;

use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool
}

fn to_hex(bytes: &[u8]) -> String {
  let mut count = 0;
  let mut result = String::with_capacity(67);
  let mut dotline = String::with_capacity(18);

  for byte in bytes.iter() {
    if count != 0 && count%8 == 0 {
      result.push(' ');
      if count%16 == 0 {
        dotline.push('\n');
        result.push_str(&dotline);
        result.reserve(67);
        dotline.truncate(0);
      }
      else { dotline.push(' '); }
    }
    result.push_str(&format!("{:02X} ", byte));
    if *byte > 31 && *byte < 127 { dotline.push(*byte as char) }
    else if *byte == 0 { dotline.push('-'); }
    else { dotline.push('.'); }
    count += 1;
  }
  while count%16 != 0 {
    if count%8 == 0 { result.push(' '); }
    result.push_str("   ");
    count += 1;
  }
  if dotline.len() != 0 { result.push_str(&dotline); }
  result
}

fn main() {
  println!("Portlurker v{}", VERSION);
  println!("{}", AUTHORS);
  println!("-----------------------------------------");

  let mut app = App { print_ascii: false, print_binary: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]"),
    ("SMB2 COMMAND NEGOTIATE", r"^\x00...\xfeSMB........\x00\x00"),
    ("SMB2 NT_STATUS Success", r"^\x00...\xfeSMB....[\x00-\x0f]"),
    ("SMB2 NT_STATUS Information", r"^\x00...\xfeSMB....[\x40-\x4f]"),
    ("SMB2 NT_STATUS Warning", r"^\x00...\xfeSMB....[\x80-\x8f]"),
    ("SMB2 NT_STATUS Error", r"^\x00...\xfeSMB....[\xc0-\xcf]"),
    ("MS-TDS PRELOGIN Request", r"^\x12\x01\x00.\x00\x00"),
    ("MS-TDS LOGIN Request", r"^\x10\x01\x00.\x00\x00"),
    ("SOCKS5 NOAUTH Request", r"^\x05\x01\x00$"),
    ("SOCKS5 NOAUTH,USER/PASS Request", r"^\x05\x02\x00\x02$")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ASCII");
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary in hexadecimal");
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  println!("\nStarting listeners on the following ports:");

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = match res {
            Ok(stream) => stream,
            Err(e) => { println!("ACCEPT ERROR TCP {}: {}", portno, e.to_string()); continue; }
          };
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);
          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("WRITE TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut mbfound = false;
                  let mut mbstring = String::new();
                  let mut start = 0;
                  for i in 0..c {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        if (i-start == 1) {
                          if (start > 0) && (buf[start-1] == 0) {
                            mbstring.push(buf[i-1] as char);
                            if !mbfound { mbfound = true; }
                          }
                        }
                        else { printables.push(&buf[start..i]); }
                        found = false;
                      }
                      else if mbfound {
                        mbstring.push('\n');
                        mbfound = false;
                      }
                    }
                  }
                  if found { printables.push(&buf[start..c]); }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ASCII", c); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("^ Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                    for line in mbstring.lines() {
                      if line.len() > 3 { println!("% {}", line); }
                    }
                    if app.print_binary {
                      let hex = to_hex(&buf[..c]);
                      for line in hex.lines() { println!(". {}", line); }
                    }
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("READ TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<|endoftext|>


<commit_before>extern crate image;

extern crate rusttracer;

use std::path::Path;
use std::env;

use rusttracer::math::Vector3;
use rusttracer::{Scene, Color, Camera, Material, Renderer, SuperSampling};
use rusttracer::geometry::{Shape, Sphere};

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 1920;
const HEIGHT: u32 = 1080;
const BUFFER_SIZE: usize = (WIDTH * HEIGHT * 3) as usize;
const DEFAULT_NUMBER_OF_THREADS: u32 = 4;

fn main() {
    let num_threads = match env::var("NUM_THREADS") {
        Ok(threads) => threads.parse::<u32>().unwrap_or(DEFAULT_NUMBER_OF_THREADS),
        Err(_) => DEFAULT_NUMBER_OF_THREADS,
    };

    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };

    let m1 = Material::new(Color::new(29, 86, 140), Color::black(), 0.0);
    let s1 = Sphere::new(Vector3::new(0.0, 0.0, 15.0), 1.0, m1);

    let m2 = Material::new(Color::new(140, 10, 29), Color::black(), 0.0);
    let s2 = Sphere::new(Vector3::new(-3.0, 0.0, 15.0), 1.0, m2);

    let m3 = Material::new(Color::new(10, 145, 29), Color::black(), 0.0);
    let s3 = Sphere::new(Vector3::new(3.0, 0.0, 15.0), 1.0, m3);

    let m4 = Material::new(Color::new(10, 145, 120), Color::black(), 0.0);
    let s4 = Sphere::new(Vector3::new(1.5, 2.0, 15.0), 0.5, m4);

    let m5 = Material::new(Color::new(190, 145, 29), Color::black(), 0.0);
    let s5 = Sphere::new(Vector3::new(-1.5, 2.0, 15.0), 0.5, m5);

    let objects: Vec<&Shape> = vec![&s1, &s2, &s3, &s4, &s5];
    let scene = Scene::new(&objects, Color::black());
    let camera = Camera::new(0.785398163, WIDTH, HEIGHT);

    let renderer = Renderer::new(&scene, &camera, SuperSampling::On(2), num_threads);

    if benchmark {
        for i in 0..10 {
            let x: Vec<Color> = renderer.render(MAX_DEPTH);
        }
    }

    let result: Vec<Color> = renderer.render(MAX_DEPTH);
    let mut buffer: [u8; BUFFER_SIZE] = [0x8C; BUFFER_SIZE];

    for (index, pixel) in result.iter().enumerate() {
        buffer[(index * 3) + 0] = pixel.r();
        buffer[(index * 3) + 1] = pixel.g();
        buffer[(index * 3) + 2] = pixel.b();
    }

    image::save_buffer(&Path::new("image.png"),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<commit_msg>Don't allocate pixel buffer on the stack<commit_after>extern crate image;

extern crate rusttracer;

use std::path::Path;
use std::env;

use rusttracer::math::Vector3;
use rusttracer::{Scene, Color, Camera, Material, Renderer, SuperSampling};
use rusttracer::geometry::{Shape, Sphere};

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 1920;
const HEIGHT: u32 = 1080;
const BUFFER_SIZE: usize = (WIDTH * HEIGHT * 3) as usize;
const DEFAULT_NUMBER_OF_THREADS: u32 = 4;

fn main() {
    let num_threads = match env::var("NUM_THREADS") {
        Ok(threads) => threads.parse::<u32>().unwrap_or(DEFAULT_NUMBER_OF_THREADS),
        Err(_) => DEFAULT_NUMBER_OF_THREADS,
    };

    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };

    let m1 = Material::new(Color::new(29, 86, 140), Color::black(), 0.0);
    let s1 = Sphere::new(Vector3::new(0.0, 0.0, 15.0), 1.0, m1);

    let m2 = Material::new(Color::new(140, 10, 29), Color::black(), 0.0);
    let s2 = Sphere::new(Vector3::new(-3.0, 0.0, 15.0), 1.0, m2);

    let m3 = Material::new(Color::new(10, 145, 29), Color::black(), 0.0);
    let s3 = Sphere::new(Vector3::new(3.0, 0.0, 15.0), 1.0, m3);

    let m4 = Material::new(Color::new(10, 145, 120), Color::black(), 0.0);
    let s4 = Sphere::new(Vector3::new(1.5, 2.0, 15.0), 0.5, m4);

    let m5 = Material::new(Color::new(190, 145, 29), Color::black(), 0.0);
    let s5 = Sphere::new(Vector3::new(-1.5, 2.0, 15.0), 0.5, m5);

    let objects: Vec<&Shape> = vec![&s1, &s2, &s3, &s4, &s5];
    let scene = Scene::new(&objects, Color::black());
    let camera = Camera::new(0.785398163, WIDTH, HEIGHT);

    let renderer = Renderer::new(&scene, &camera, SuperSampling::On(2), num_threads);

    if benchmark {
        for i in 0..10 {
            let x: Vec<Color> = renderer.render(MAX_DEPTH);
        }
    }

    let result: Vec<Color> = renderer.render(MAX_DEPTH);
    let mut buffer = vec![0x8C; BUFFER_SIZE];

    for (index, pixel) in result.iter().enumerate() {
        buffer[(index * 3) + 0] = pixel.r();
        buffer[(index * 3) + 1] = pixel.g();
        buffer[(index * 3) + 2] = pixel.b();
    }

    image::save_buffer(&Path::new("image.png"),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chip8_vm;

use std::cell::RefCell;
use std::rc::Rc;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

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

    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            error!("Could not open ROM {}", rom_path);
        }
    }

    // rustc warns about the "trivial casts" to Read,
    // but without those the match arms are incompatible.
    // This part of the code might be obsoleted by #26
    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            info!("You can provide a path to a CHIP-8 ROM to run it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => debug!("Loaded ROM of size: {}", size),
        Err(e) => {
            error!("Error loading ROM: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let settings = WindowSettings::new(
        TITLE.to_string(),
        window::Size {
            width: width,
            height: height
        }
    );
    let window = Sdl2Window::new(
        opengl,
        settings
    );

    let ref mut gl = Gl::new(opengl);
    let window = Rc::new(RefCell::new(window));

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(window.clone()) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (window.borrow_mut()).window.set_title(BEEP_TITLE);
            } else {
                (window.borrow_mut()).window.set_title(TITLE);
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = [0.0, 0.0, 0.0, 1.0];
                let on = [1.0, 1.0, 1.0, 1.0];

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        let color = match *byte { 0 => off, _ => on };
                        r.color(color).draw([x, y, w, h], &c.draw_state, c.transform, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<commit_msg>Silence unused result warning by unwrapping<commit_after>#![cfg_attr(test, allow(dead_code))]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chip8_vm;

use std::cell::RefCell;
use std::rc::Rc;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

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

    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            error!("Could not open ROM {}", rom_path);
        }
    }

    // rustc warns about the "trivial casts" to Read,
    // but without those the match arms are incompatible.
    // This part of the code might be obsoleted by #26
    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            info!("You can provide a path to a CHIP-8 ROM to run it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => debug!("Loaded ROM of size: {}", size),
        Err(e) => {
            error!("Error loading ROM: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let settings = WindowSettings::new(
        TITLE.to_string(),
        window::Size {
            width: width,
            height: height
        }
    );
    let window = Sdl2Window::new(
        opengl,
        settings
    );

    let ref mut gl = Gl::new(opengl);
    let window = Rc::new(RefCell::new(window));

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(window.clone()) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (window.borrow_mut()).window.set_title(BEEP_TITLE).unwrap();
            } else {
                (window.borrow_mut()).window.set_title(TITLE).unwrap();
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = [0.0, 0.0, 0.0, 1.0];
                let on = [1.0, 1.0, 1.0, 1.0];

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        let color = match *byte { 0 => off, _ => on };
                        r.color(color).draw([x, y, w, h], &c.draw_state, c.transform, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<|endoftext|>


<commit_before>extern crate unicode_names;
extern crate byteorder;

use std::env;
use std::fmt;
use std::str;
use std::char;

use byteorder::{ByteOrder, BigEndian};

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let quote : String = self.c.escape_default().collect();
        try!(write!(f, "; prints as {}", quote));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {} = {}\n",
                       self.c, n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> std::convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> std::convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns either None (if the
/// character description is not understood), or Some(Describable)
/// that holds the character.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut chars: Vec<char> = Vec::new();

    // match the character itself, or any of its names:
    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| chars.push(c));
    } else {
        unicode_names::character(spec).map(|c| chars.push(c));
    }
    // Match hex strings specifically:
    if spec.starts_with("0x") || spec.starts_with("U+") {
        let _ = u32::from_str_radix(&spec[2..], 16).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }

    // Match plain numbers in all bases:
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }
    chars.sort_by(|a, b| b.cmp(a));
    chars.dedup();
    chars.iter().map(|c| c.clone().into()).collect()
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('n', from_arg("n")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('n', from_arg("latin small letter n")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);

    assert_eq!(2, from_arg("0").len());
    assert_eq!(0x30, from_arg("0").iter().next().unwrap().c as u32);

    assert_eq!(1, from_arg("0x0").len());
    assert_eq!(1, from_arg("0x41").len());
    assert_eq!('A', from_arg("0x41")[0].c);
}
<commit_msg>Straighten out character/escape printing<commit_after>extern crate unicode_names;
extern crate byteorder;

use std::env;
use std::fmt;
use std::str;
use std::char;

use byteorder::{ByteOrder, BigEndian};

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let printable : Printable = self.c.into();
        try!(write!(f, "\n{}", printable));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {}\n", n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

struct Printable {
    c: char,
}

impl std::convert::From<char> for Printable {
    fn from(c: char) -> Printable {
        Printable{c: c}
    }
}

impl fmt::Display for Printable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let quote : String = self.c.escape_default().collect();
        if self.c.is_control() {
            try!(write!(f, "Control character; quotes as {}", quote));
        } else {
            if ! self.c.is_whitespace() {
                try!(write!(f, "Prints as {}", self.c));
            } else {
                try!(write!(f, "Prints as `{}'", self.c));
            }
            // Check if we can up/downcase:
            let mut caseflipped = String::new();
            if self.c.is_uppercase() {
                for c in self.c.to_lowercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nLower case {}", caseflipped));
            } else if self.c.is_lowercase() {
                for c in self.c.to_uppercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nUpper case {}", caseflipped));
            }

            // If we have quotable text, print that too:
            if quote.len() > 1 {
                try!(write!(f, "\nQuotes as {}", quote));
            }
        }
        Ok(())
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> std::convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> std::convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns a Vec of Describable
/// elements that hold the corresponding character. The elements of
/// the vector are sorted by descending numeric code point.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut chars: Vec<char> = Vec::new();

    // match the character itself, or any of its names:
    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| chars.push(c));
    } else {
        unicode_names::character(spec).map(|c| chars.push(c));
    }
    // Match hex/U+ strings specifically:
    if spec.starts_with("0x") || spec.starts_with("U+") {
        let _ = u32::from_str_radix(&spec[2..], 16).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }

    // Match plain numbers in all bases:
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }
    chars.sort_by(|a, b| b.cmp(a));
    chars.dedup();
    chars.iter().map(|c| c.clone().into()).collect()
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('n', from_arg("n")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('n', from_arg("latin small letter n")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);

    assert_eq!(2, from_arg("0").len());
    assert_eq!(0x30, from_arg("0").iter().next().unwrap().c as u32);

    assert_eq!(1, from_arg("0x0").len());
    assert_eq!(1, from_arg("0x41").len());
    assert_eq!('A', from_arg("0x41")[0].c);
}
<|endoftext|>