<commit_before>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: main.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Entry point.
*/

extern mod std;
extern mod opengles;
extern mod glfw;

#[path = "gl/mod.rs"]
mod gl;

#[path = "math/mod.rs"]
mod math;

#[macro_escape]
#[path = "gl/check.rs"]
mod check;

#[path = "obj/bsp/mod.rs"]
mod bsp;

#[path = "gl/ttf/mod.rs"]
mod ttf;

#[path = "obj/primitive/mod.rs"]
mod primitive;

#[path = "obj/voxel/mod.rs"]
mod voxel;

fn main() {
  glfw::set_error_callback(error_callback);

  do glfw::spawn {
    glfw::window_hint::context_version(3, 2);
    glfw::window_hint::opengl_profile(glfw::OPENGL_CORE_PROFILE);
    glfw::window_hint::opengl_forward_compat(true);

    let window_res = glfw::Window::create(1024, 768, "Q^3", glfw::Windowed);
    if window_res.is_err()
    { fail!(window_res.get_err()); }
    let window = @window_res.get();
    window.make_context_current();

    let camera = @mut gl::Camera::new(window);
    camera.init();

    /* Setup callbacks. */
    window.set_cursor_mode(glfw::CURSOR_CAPTURED);
    do window.set_size_callback |_, width, height|
    { camera.resize(width as i32, height as i32); }
    do window.set_cursor_pos_callback |_, x, y|
    { camera.mouse_moved(x, y); }
    do window.set_key_callback |window, key, action|
    {
      camera.key_action(key, action);
      key_callback(window, key, action);
    }

    let mut sphere = primitive::Sphere::new(100.0, 5);

    let map = bsp::Map::new("data/q3ctf1.bsp");
    //let map = map::Map::new("data/dk.bsp");

    io::println(fmt!("Map has %? tris", map.tris.len()));
    let st = std::time::precise_time_s();
    let vox_sphere = voxel::Map::new(sphere.tris, 10);
    let vox_map = voxel::Map::new(map.tris, 100);
    let et = std::time::precise_time_s();
    io::println(fmt!("Voxel map creation took %? seconds.", (et - st)));

    /* Temp test for font loading. */
    let mut font_renderer = ttf::Renderer::new();
    let mut font = ttf::Font::new("data/test.ttf", 50);

    /* Shader Creation. */
    let shader = @mut gl::Shader_Builder::new_with_files("data/shaders/voxel.vert", "data/shaders/voxel.frag");
    shader.bind();

    let proj_loc = shader.get_uniform_location(~"proj");
    let world_loc = shader.get_uniform_location(~"world");
    let voxel_size_loc = shader.get_uniform_location(~"voxel_size");

    let mut cur_time = (std::time::precise_time_ns() / 10000) as f32; // Hundredth of a second
    let mut last_time = cur_time;

    while !window.should_close() {
      glfw::poll_events();

      /* Delta time. */
      let delta = cur_time - last_time;
      last_time = cur_time;
      cur_time = (std::time::precise_time_ns() / 10000) as f32;

      camera.update(delta);
      shader.bind();
      shader.update_uniform_mat(proj_loc, camera.projection);
      shader.update_uniform_mat(world_loc, camera.view);

      let fps = camera.frame_rate;

      check!(gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
      {
        //check!(gl::draw_arrays_instanced(gl::TRIANGLES, 0, 36, (10 * 10 * 10)));
        //map.draw();
        //sphere.draw();

        shader.update_uniform_f32(voxel_size_loc, vox_sphere.voxel_size);
        vox_sphere.draw();

        shader.update_uniform_f32(voxel_size_loc, vox_map.voxel_size);
        vox_map.draw();

        font_renderer.begin(camera);
        font_renderer.render(fmt!("%?", fps), math::Vec2f::new(0.0, 0.0), &font);
        font_renderer.end();
      } window.swap_buffers();

      //std::timer::sleep(@std::uv::global_loop::get(), 1000 / (camera.target_frame_rate as uint));
    }
  }
}

fn key_callback(window: &glfw::Window, key: libc::c_int, action: libc::c_int)
{
  if action == glfw::PRESS && key == glfw::KEY_ESCAPE
  { window.set_should_close(true); }
}

fn error_callback(error: libc::c_int, description: ~str)
{ error!("GLFW Error %?: %s", error, description); }

<commit_msg> #12 Render regular map and voxel map to compare<commit_after>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: main.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Entry point.
*/

extern mod std;
extern mod opengles;
extern mod glfw;

#[path = "gl/mod.rs"]
mod gl;

#[path = "math/mod.rs"]
mod math;

#[macro_escape]
#[path = "gl/check.rs"]
mod check;

#[path = "obj/bsp/mod.rs"]
mod bsp;

#[path = "gl/ttf/mod.rs"]
mod ttf;

#[path = "obj/primitive/mod.rs"]
mod primitive;

#[path = "obj/voxel/mod.rs"]
mod voxel;

fn main() {
  glfw::set_error_callback(error_callback);

  do glfw::spawn {
    glfw::window_hint::context_version(3, 2);
    glfw::window_hint::opengl_profile(glfw::OPENGL_CORE_PROFILE);
    glfw::window_hint::opengl_forward_compat(true);

    let window_res = glfw::Window::create(1024, 768, "Q^3", glfw::Windowed);
    if window_res.is_err()
    { fail!(window_res.get_err()); }
    let window = @window_res.get();
    window.make_context_current();

    let camera = @mut gl::Camera::new(window);
    camera.init();

    /* Setup callbacks. */
    window.set_cursor_mode(glfw::CURSOR_CAPTURED);
    do window.set_size_callback |_, width, height|
    { camera.resize(width as i32, height as i32); }
    do window.set_cursor_pos_callback |_, x, y|
    { camera.mouse_moved(x, y); }
    do window.set_key_callback |window, key, action|
    {
      camera.key_action(key, action);
      key_callback(window, key, action);
    }

    let mut sphere = primitive::Sphere::new(100.0, 5);

    let map = bsp::Map::new("data/q3ctf1.bsp");
    //let map = map::Map::new("data/dk.bsp");

    io::println(fmt!("Map has %? tris", map.tris.len()));
    let st = std::time::precise_time_s();
    let vox_sphere = voxel::Map::new(sphere.tris, 10);
    let vox_map = voxel::Map::new(map.tris, 100);
    let et = std::time::precise_time_s();
    io::println(fmt!("Voxel map creation took %? seconds.", (et - st)));

    /* Temp test for font loading. */
    let mut font_renderer = ttf::Renderer::new();
    let mut font = ttf::Font::new("data/test.ttf", 50);

    /* Shader Creation. */
    let shader = @mut gl::Shader_Builder::new_with_files("data/shaders/voxel.vert", "data/shaders/voxel.frag");
    let color_shader = @mut gl::Shader_Builder::new_with_files("data/shaders/color.vert", "data/shaders/color.frag");
    shader.bind();

    let proj_loc = shader.get_uniform_location(~"proj");
    let world_loc = shader.get_uniform_location(~"world");
    let voxel_size_loc = shader.get_uniform_location(~"voxel_size");
    let color_proj_loc = color_shader.get_uniform_location(~"proj");
    let color_world_loc = color_shader.get_uniform_location(~"world");
    let color_voxel_size_loc = color_shader.get_uniform_location(~"voxel_size");

    let mut cur_time = (std::time::precise_time_ns() / 10000) as f32; // Hundredth of a second
    let mut last_time = cur_time;

    while !window.should_close() {
      glfw::poll_events();

      /* Delta time. */
      let delta = cur_time - last_time;
      last_time = cur_time;
      cur_time = (std::time::precise_time_ns() / 10000) as f32;

      camera.update(delta);
      shader.bind();
      shader.update_uniform_mat(proj_loc, camera.projection);
      shader.update_uniform_mat(world_loc, camera.view);
      color_shader.bind();
      color_shader.update_uniform_mat(color_proj_loc, camera.projection);
      color_shader.update_uniform_mat(color_world_loc, camera.view);

      let fps = camera.frame_rate;

      check!(gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
      {
        //check!(gl::draw_arrays_instanced(gl::TRIANGLES, 0, 36, (10 * 10 * 10)));
        color_shader.bind();
        map.draw();
        //sphere.draw();

        shader.bind();
        shader.update_uniform_f32(voxel_size_loc, vox_sphere.voxel_size);
        //vox_sphere.draw();

        shader.update_uniform_f32(voxel_size_loc, vox_map.voxel_size);
        vox_map.draw();

        font_renderer.begin(camera);
        font_renderer.render(fmt!("%?", fps), math::Vec2f::new(0.0, 0.0), &font);
        font_renderer.end();
      } window.swap_buffers();

      //std::timer::sleep(@std::uv::global_loop::get(), 1000 / (camera.target_frame_rate as uint));
    }
  }
}

fn key_callback(window: &glfw::Window, key: libc::c_int, action: libc::c_int)
{
  if action == glfw::PRESS && key == glfw::KEY_ESCAPE
  { window.set_should_close(true); }
}

fn error_callback(error: libc::c_int, description: ~str)
{ error!("GLFW Error %?: %s", error, description); }

<|endoftext|>


<commit_before>extern crate libc;
extern crate image;

mod cudart;
mod cudnn;
mod cifar;
mod util;

use std::process::exit;
use std::path::Path;
use std::env;

fn run(args: Vec<String>) -> Result<(), &'static str> {
    let cudnn = try!{ cudnn::Cudnn::new() };

    let cifar = cifar::Cifar::new(&args[1]);
    let image = cifar.images.iter().nth(9999).unwrap();

    // alloc device memory
    let _src_desc = try! { cudnn::Tensor::new_4d(1, 3, 32, 32) };
    let _dst_desc = try! { cudnn::Tensor::new_4d(1, 3, 32, 32) };
    let mut dst = try! { cudart::Memory::<f32>::new(32 * 32 * 3) };
    let src = try! { image.to_device() };
    try! { cudnn.sigmoid_forward(_src_desc, &src, _dst_desc, &mut dst) };
    let img = try! { util::Image::from_device(dst, 1u8, 32, 32) };

    // write png image
    img.save("images/cifar.png")
}

fn main() {
    match run(env::args().collect()) {
        Ok(_) => exit(0),
        Err(e) => {
            println!("{}", e);
            exit(1)
        }
    }
}
<commit_msg>simplified the namespace usage<commit_after>extern crate libc;
extern crate image;

mod cudart;
mod cudnn;
mod cifar;
mod util;

use cudnn::{Cudnn, Tensor};
use cudart::{Memory};
use util::{Image};
use cifar::{Cifar};
use std::process::exit;
use std::path::Path;
use std::env;

fn run(args: Vec<String>) -> Result<(), &'static str> {
    let cudnn = try!{ Cudnn::new() };

    let cifar = Cifar::new(&args[1]);
    let image = cifar.images.iter().nth(9999).unwrap();

    // alloc device memory
    let _src_desc = try! { Tensor::new_4d(1, 3, 32, 32) };
    let _dst_desc = try! { Tensor::new_4d(1, 3, 32, 32) };
    let mut dst = try! { Memory::<f32>::new(32 * 32 * 3) };
    let src = try! { image.to_device() };
    try! { cudnn.sigmoid_forward(_src_desc, &src, _dst_desc, &mut dst) };
    let img = try! { Image::from_device(dst, 1u8, 32, 32) };

    // write png image
    img.save("images/cifar.png")
}

fn main() {
    match run(env::args().collect()) {
        Ok(_) => exit(0),
        Err(e) => {
            println!("{}", e);
            exit(1)
        }
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate pnet;

use getopts::Options;
use std::os;
use std::net::{IpAddr};
use std::str::FromStr;

use pnet::transport::TransportProtocol::{Ipv4};
use pnet::old_packet::ip::IpNextHeaderProtocols;
use pnet::transport::TransportChannelType::{Layer3};
use pnet::transport::{transport_channel};
use pnet::old_packet::ipv4::{Ipv4Header, Ipv4Packet};

fn main() {
    let args: Vec<String> = os::args();
    let mut opts = Options::new();
    let matches = match opts.parse(args.tail()) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let addr_arg = matches.free[0].as_slice();
    let addr: IpAddr = FromStr::from_str(addr_arg.as_slice()).unwrap();

    let protocol = Layer3(IpNextHeaderProtocols::Test1);
    let (mut icmp_sender, mut icmp_receiver) = match transport_channel(4096, protocol) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("An error occurred when creating the transport channel:
                        {}", e)
    };
    let packet = build_icmp_time_request_packet();
}

fn build_icmp_time_request_packet() -> IcmpRequestPacket {
    let ip_type = 14u8;
    let ip_code = 0u8;
    let ip_checksum = 0u16; // calculate; 16 bits
    let identifier = 0u16; // what should this be? used to match requests to replies; 16 bits
    let sequence = 0u16; // what should this be? used to match requests to replies;
    let originate_timestamp = 0u32; // get from systime
    let receive_timestamp = 0u32; // not used
    let transmit_timestamp = 0u32; // not used
    let mut packet = IcmpRequestPacket::new();
    packet
}

struct IcmpRequestPacket {
    ip_type: u8,
    ip_code: u8,
    ip_checksum: u16,
    identifier: u16,
    sequence: u16,
    originate_timestamp: u32,
    receive_timestamp: u32,
    transmit_timestamp: u32
}

impl IcmpRequestPacket {
    fn new() -> IcmpRequestPacket {
        let mut packet = IcmpRequestPacket {
            ip_type: 13,
            ip_code: 0,
            ip_checksum: 0,
            identifier: 0,
            sequence: 0,
            originate_timestamp: 0,
            receive_timestamp: 0,
            transmit_timestamp: 0
        };
        packet.set_checksum();
        packet
    }

    fn calculate_checksum(&self) -> u16 {
        // implement me
        1
    }

    fn set_checksum(&mut self) {
        self.ip_checksum = self.calculate_checksum();
    }
}
<commit_msg>set packet originate timestamp<commit_after>extern crate getopts;
extern crate pnet;
extern crate time;

use getopts::Options;
use std::os;
use std::net::{IpAddr};
use std::str::FromStr;

use pnet::transport::TransportProtocol::{Ipv4};
use pnet::old_packet::ip::IpNextHeaderProtocols;
use pnet::transport::TransportChannelType::{Layer3};
use pnet::transport::{transport_channel};
use pnet::old_packet::ipv4::{Ipv4Header, Ipv4Packet};

fn main() {
    let args: Vec<String> = os::args();
    let mut opts = Options::new();
    let matches = match opts.parse(args.tail()) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let addr_arg = matches.free[0].as_slice();
    let addr: IpAddr = FromStr::from_str(addr_arg.as_slice()).unwrap();

    let protocol = Layer3(IpNextHeaderProtocols::Test1);
    let (mut icmp_sender, mut icmp_receiver) = match transport_channel(4096, protocol) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("An error occurred when creating the transport channel:
                        {}", e)
    };
    let packet = build_icmp_time_request_packet();
}

fn build_icmp_time_request_packet() -> IcmpRequestPacket {
    let ip_type = 14u8;
    let ip_code = 0u8;
    let ip_checksum = 0u16; // calculate; 16 bits
    let identifier = 0u16; // what should this be? used to match requests to replies; 16 bits
    let sequence = 0u16; // what should this be? used to match requests to replies;
    let originate_timestamp = 0u32; // get from systime
    let receive_timestamp = 0u32; // not used
    let transmit_timestamp = 0u32; // not used
    let mut packet = IcmpRequestPacket::new();
    packet
}

struct IcmpRequestPacket {
    ip_type: u8,
    ip_code: u8,
    ip_checksum: u16,
    identifier: u16,
    sequence: u16,
    originate_timestamp: u32,
    receive_timestamp: u32,
    transmit_timestamp: u32
}

impl IcmpRequestPacket {
    fn new() -> IcmpRequestPacket {
        let mut packet = IcmpRequestPacket {
            ip_type: 13,
            ip_code: 0,
            ip_checksum: 0,
            identifier: 0,
            sequence: 0,
            originate_timestamp: 0,
            receive_timestamp: 0,
            transmit_timestamp: 0
        };
        packet.set_originate_timestamp();
        packet.set_checksum();
        packet
    }

    fn calculate_checksum(&self) -> u16 {
        // implement me
        let mut vec: Vec<u16> = vec![];
        1
    }

    fn set_checksum(&mut self) {
        self.ip_checksum = self.calculate_checksum();
    }

    fn set_originate_timestamp(&mut self) {
        self.originate_timestamp = time_after_utc();
    }
}

fn time_after_utc() -> u32 {
    let t = time::now_utc();
    let s: i32 = t.tm_hour * 3600 + t.tm_min * 60 + t.tm_sec;
    s as u32
}
<|endoftext|>


<commit_before>use fluent_langneg::{accepted_languages, negotiate_languages, NegotiationStrategy};
use fluent_resmgr::resource_manager::ResourceManager;
use git2::Repository;
use regex::Regex;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind};
use std::path;
use std::vec;
use structopt::clap::AppSettings;
use structopt::StructOpt;
use unic_langid::LanguageIdentifier;

/// The command line interface to the CaSILE toolkit, a book publishing
/// workflow employing SILE and other wizardry
#[derive(StructOpt)]
#[structopt(version = env!("VERGEN_SEMVER"))]
#[structopt(setting = AppSettings::InferSubcommands)]
struct Cli {
    /// Activate debug mode
    #[structopt(short, long, env = "DEBUG")]
    debug: bool,

    /// Set language
    #[structopt(short, long, env = "LANG")]
    language: String,

    /// Outputs verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    #[structopt(subcommand)]
    subcommand: Subcommand,
}

#[derive(StructOpt)]
enum Subcommand {
    /// Executes a make target
    Make {
        /// Target as defined in CaSILE makefile
        target: Vec<String>,
    },

    /// Configure a book repository
    Setup {
        /// Path to project repository
        #[structopt(parse(from_os_str), default_value = "./")]
        path: path::PathBuf,
    },

    /// Pass through other commands to shell
    #[structopt(external_subcommand)]
    Other(Vec<String>),
}

fn main() -> io::Result<()> {
    let args = Cli::from_args();

    if args.debug {
        println!("User requested debug mode")
    }

    if args.verbose {
        println!("User requested verbose output")
    }

    let available = get_available_locales().expect("Could not find valid BCP47 resource files.");

    let re = Regex::new(r"\..*$").unwrap();
    let input = re.replace(&args.language, "");
    let requested = accepted_languages::parse(&input);
    let default: LanguageIdentifier = "en-US".parse().unwrap();

    let language = negotiate_languages(
        &requested,
        &available,
        Some(&default),
        NegotiationStrategy::Filtering,
    );

    println!("Lang ended up {:?}", language[0]);

    match args.subcommand {
        Subcommand::Make { target } => make(target),
        Subcommand::Setup { path } => setup(path),
        _a => shell(),
    }
}

fn make(_target: vec::Vec<String>) -> io::Result<()> {
    println!("Make make make sense or I’ll make you make makefiles.");
    Ok(())
}

fn setup(path: path::PathBuf) -> io::Result<()> {
    let metadata = fs::metadata(&path)?;
    match metadata.is_dir() {
        true => match Repository::open(path) {
            Ok(_repo) => Ok(println!(
                "Run setup, “They said you were this great colossus!”"
            )),
            Err(_error) => Err(Error::new(ErrorKind::InvalidInput, "Not a git repo!")),
        },
        false => Err(Error::new(ErrorKind::InvalidInput, "Not a dir, Frank!")),
    }
}

fn shell() -> io::Result<()> {
    println!("Ship all this off to the shell, maybe they can handle it.");
    Ok(())
}

// TODO: Move to build.rs?
// https://github.com/projectfluent/fluent-rs/blob/c9e45651/fluent-resmgr/examples/simple-resmgr.rs#L35
fn get_available_locales() -> Result<Vec<LanguageIdentifier>, io::Error> {
    let mut locales = vec![];
    let res_dir = fs::read_dir("./resources/")?;
    for entry in res_dir {
        if let Ok(entry) = entry {
            let path = entry.path();
            if path.is_dir() {
                if let Some(name) = path.file_name() {
                    if let Some(name) = name.to_str() {
                        let langid: LanguageIdentifier =
                            name.parse().expect("Could not parse BCP47 language tag.");
                        locales.push(langid);
                    }
                }
            }
        }
    }
    return Ok(locales);
}
<commit_msg>chore(cli): Use Fluent bundle manager to load and format a message<commit_after>use fluent_langneg::{accepted_languages, negotiate_languages, NegotiationStrategy};
use fluent_resmgr::resource_manager::ResourceManager;
use git2::Repository;
use regex::Regex;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind};
use std::path;
use std::vec;
use structopt::clap::AppSettings;
use structopt::StructOpt;
use unic_langid::LanguageIdentifier;

/// The command line interface to the CaSILE toolkit, a book publishing
/// workflow employing SILE and other wizardry
#[derive(StructOpt)]
#[structopt(version = env!("VERGEN_SEMVER"))]
#[structopt(setting = AppSettings::InferSubcommands)]
struct Cli {
    /// Activate debug mode
    #[structopt(short, long, env = "DEBUG")]
    debug: bool,

    /// Set language
    #[structopt(short, long, env = "LANG")]
    language: String,

    /// Outputs verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    #[structopt(subcommand)]
    subcommand: Subcommand,
}

#[derive(StructOpt)]
enum Subcommand {
    /// Executes a make target
    Make {
        /// Target as defined in CaSILE makefile
        target: Vec<String>,
    },

    /// Configure a book repository
    Setup {
        /// Path to project repository
        #[structopt(parse(from_os_str), default_value = "./")]
        path: path::PathBuf,
    },

    /// Pass through other commands to shell
    #[structopt(external_subcommand)]
    Other(Vec<String>),
}

fn main() -> io::Result<()> {
    let args = Cli::from_args();

    if args.debug {
        println!("User requested debug mode")
    }

    if args.verbose {
        println!("User requested verbose output")
    }

    let available = get_available_locales().expect("Could not find valid BCP47 resource files.");
    let re = Regex::new(r"\..*$").unwrap();
    let input = re.replace(&args.language, "");
    let requested = accepted_languages::parse(&input);
    let default: LanguageIdentifier = "en-US".parse().unwrap();
    let resolved_locales = negotiate_languages(
        &requested,
        &available,
        Some(&default),
        NegotiationStrategy::Filtering,
    );
    println!("Lang ended up {:?}", resolved_locales[0]);
    let resources: vec::Vec<String> = vec!["cli.ftl".into()];
    let mgr = ResourceManager::new("./resources/{locale}/{res_id}".into());
    let bundle = mgr.get_bundle(
        resolved_locales.into_iter().map(|s| s.to_owned()).collect(),
        resources,
    );

    let mut errors = vec![];
    let msg = bundle.get_message("debug-shell").expect("Message exists");
    let pattern = msg.value.expect("Message has a value");
    let value = bundle.format_pattern(&pattern, None, &mut errors);
    println!("Message is: {}", value);

    match args.subcommand {
        Subcommand::Make { target } => make(target),
        Subcommand::Setup { path } => setup(path),
        _a => shell(),
    }
}

fn make(_target: vec::Vec<String>) -> io::Result<()> {
    println!("Make make make sense or I’ll make you make makefiles.");
    Ok(())
}

fn setup(path: path::PathBuf) -> io::Result<()> {
    let metadata = fs::metadata(&path)?;
    match metadata.is_dir() {
        true => match Repository::open(path) {
            Ok(_repo) => Ok(println!(
                "Run setup, “They said you were this great colossus!”"
            )),
            Err(_error) => Err(Error::new(ErrorKind::InvalidInput, "Not a git repo!")),
        },
        false => Err(Error::new(ErrorKind::InvalidInput, "Not a dir, Frank!")),
    }
}

fn shell() -> io::Result<()> {
    println!("Ship all this off to the shell, maybe they can handle it.");
    Ok(())
}

// TODO: Move to build.rs?
// https://github.com/projectfluent/fluent-rs/blob/c9e45651/fluent-resmgr/examples/simple-resmgr.rs#L35
fn get_available_locales() -> Result<Vec<LanguageIdentifier>, io::Error> {
    let mut locales = vec![];
    let res_dir = fs::read_dir("./resources/")?;
    for entry in res_dir {
        if let Ok(entry) = entry {
            let path = entry.path();
            if path.is_dir() {
                if let Some(name) = path.file_name() {
                    if let Some(name) = name.to_str() {
                        let langid: LanguageIdentifier =
                            name.parse().expect("Could not parse BCP47 language tag.");
                        locales.push(langid);
                    }
                }
            }
        }
    }
    return Ok(locales);
}
<|endoftext|>


<commit_before>#![feature(old_io)]

extern crate term;
use std::thread;

fn main() {
    let mut t = term::stdout().unwrap();

    for i in 0..1000 {
        thread::spawn(move || {
            println!("from thread {}", i);
        });
    }

    t.fg(term::color::RED).unwrap();
    writeln!(t, "this  is a test").unwrap();
}
<commit_msg>FizzBuzz<commit_after>fn main() {

    for i in 1..100 {
        println!(
            "{}",
            if div_by_fifteen(i) { "FizzBuzz".to_string() }
            else if div_by_three(i) { "Fizz".to_string() }
            else if div_by_five(i) { "Buzz".to_string() }
            else { i.to_string() });
    }

}

fn div_by_three(num: u64) -> bool {
    (num % 3) == 0
}

fn div_by_five(num: u64) -> bool {
    (num % 5) == 0
}

fn div_by_fifteen(num: u64) -> bool {
    div_by_five(num) && div_by_three(num)
}

#[cfg(test)]
mod test {

    use super::div_by_three;

    #[test]
    fn test_div_by_three_returns_false() {

        assert_eq!(false, div_by_three(1));
        assert_eq!(false, div_by_three(2));

        assert_eq!(false, div_by_three(4));
        assert_eq!(false, div_by_three(5));
    }

    #[test]
    fn test_div_by_three_returns_true() {

        for i in 1..300 {
            assert_eq!(true, div_by_three(3 * i));
        }
    }
}
<|endoftext|>


<commit_before>#![feature(io, std_misc, path, path_ext, file_path, exit_status)]

extern crate time;

use std::fs::{File, create_dir, OpenOptions, remove_file};
use std::io::{Seek, SeekFrom, BufReader, BufReadExt, Lines, Write};
use std::io;
use std::path::{Path, PathBuf};
use std::fs::PathExt;
use std::env::{args, home_dir, set_exit_status};
use std::fmt;
use std::error::FromError;
use std::time::Duration;
use time::{now_utc, Tm, empty_tm, strptime};

fn main() {
    let result = match args().nth(1) {
        None => Err(PunchClockError::NoCommandGiven),
        Some(command) => {
            let mut time_clock = TimeClock::new().unwrap();
            match &command[..] {
                "in" => time_clock.punch_in(),
                "out" => time_clock.punch_out(),
                "status" => time_clock.status(),
                "report" => time_clock.report_daily_hours(),
                _ => Err(PunchClockError::UnknownCommand)
            }
        }
    };

    if let Err(e) = result {
        println!("Error: {}", e);
        set_exit_status(1);
    }
}

#[derive(Debug)]
enum PunchClockError {
    NoCommandGiven,
    UnknownCommand,
    AlreadyPunchedIn,
    AlreadyPunchedOut,
    CorruptedTimeSheet,
    IoError(io::Error),
}

impl fmt::Display for PunchClockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use PunchClockError::*;
        fmt.write_str(
            match *self {
                NoCommandGiven => "No command given",
                UnknownCommand => "Unknown command",
                AlreadyPunchedIn => "You are already punched in",
                AlreadyPunchedOut => "You're not currently punched in",
                CorruptedTimeSheet => "Bad data in timesheet",
                IoError(_) => "IO error"
            }
        )
    }
}

impl FromError<io::Error> for PunchClockError {
    fn from_error(err: io::Error) -> PunchClockError {
        PunchClockError::IoError(err)
    }
}

type PunchClockResult<T> = Result<T, PunchClockError>;

struct TimeClock {
    now: Tm,
    timesheet: File,
    currently_working: bool,
    state_path: PathBuf
}

impl TimeClock {
    fn new() -> PunchClockResult<TimeClock> {
        let now = now_utc();
        let home = home_dir().unwrap();
        let base_dir = home.join(Path::new(".punch"));
        let timesheet_path = base_dir.join("timesheet");
        let working_state_path = base_dir.join("state");
        if !base_dir.exists() {
            try!(create_dir(&base_dir));
        }
        let timesheet = try!(OpenOptions::new().write(true).append(true)
                            .open(&timesheet_path));
        Ok(TimeClock {
            timesheet: timesheet,
            currently_working: working_state_path.exists(),
            state_path: working_state_path,
            now: now
        })
    }

    // commands

    fn punch_in(&mut self) -> PunchClockResult<()> {
        if self.currently_working {
            return Err(PunchClockError::AlreadyPunchedIn);
        }
        try!(self.timesheet.seek(SeekFrom::End(0)));
        writeln!(&mut self.timesheet, "in: {}", self.now.rfc822()).unwrap();
        self.set_current_working_state(true);
        Ok(())
    }

    fn punch_out(&mut self) -> PunchClockResult<()> {
        if !self.currently_working {
            return Err(PunchClockError::AlreadyPunchedOut);
        }
        try!(self.timesheet.seek(SeekFrom::End(0)));
        try!(writeln!(&mut self.timesheet, "out: {}", self.now.rfc822()));
        self.set_current_working_state(false);
        Ok(())
    }

    fn status(&self) -> PunchClockResult<()> {
        if self.currently_working {
            println!("You're punched in");
        } else {
            println!("You're punched out");
        }
        Ok(())
    }

    fn report_daily_hours(&mut self) -> PunchClockResult<()> {
        try!(self.timesheet.seek(SeekFrom::Start(0)));
        let buf = BufReader::new(try!(File::open(self.timesheet.path().unwrap())));
        let mut current_day = empty_tm();
        let mut time_worked_today = Duration::zero();

        for interval in IntervalIter::from_lines(buf.lines()) {
            let (start, end) = try!(interval);
            if !same_day(&start, &current_day) {
                if !time_worked_today.is_zero() {
                    print_time_worked(&time_worked_today, &current_day);
                }
                current_day = start;
                time_worked_today = Duration::zero();
            }
            time_worked_today =
                time_worked_today + (end.to_timespec() - start.to_timespec());
        }

        if !time_worked_today.is_zero() {
            print_time_worked(&time_worked_today, &current_day);
        }
        Ok(())
    }

    // aux. methods

    fn set_current_working_state(&mut self, currently_working: bool) {
        self.currently_working = currently_working;
        if currently_working {
            File::create(&self.state_path).unwrap();
        } else {
            remove_file(&self.state_path).unwrap();
        }
    }
}

struct IntervalIter {
    lines: Lines<BufReader<File>>
}

impl IntervalIter {
    fn from_lines(lines: Lines<BufReader<File>>) -> IntervalIter {
        IntervalIter {lines: lines}
    }
}

impl Iterator for IntervalIter {
    type Item = PunchClockResult<(Tm, Tm)>;
    fn next(&mut self) -> Option<PunchClockResult<(Tm, Tm)>> {

        // helper function to make error handling a bit nicer
        fn inner_unwrap<T>(x: Option<io::Result<T>>)
                -> PunchClockResult<Option<T>> {
            match x {
                None => Ok(None),
                Some(Ok(inner)) => Ok(Some(inner)),
                Some(Err(e)) => Err(PunchClockError::IoError(e))
            }
        }

        let line_1 = match inner_unwrap(self.lines.next()) {
            Ok(l) => l,
            Err(e) => return Some(Err(e))
        };
        let line_2 = match inner_unwrap(self.lines.next()) {
            Ok(l) => l,
            Err(e) => return Some(Err(e))
        };

        match (line_1, line_2) {
            (None, None) => None,
            (Some(start_line), o_end_line) => {
                if !start_line.starts_with("in: ") {
                    return Some(Err(PunchClockError::CorruptedTimeSheet));
                }
                let start = parse_time(&start_line[4..]);
                let end = match o_end_line {
                    None => now_utc(),
                    Some(end_line) => {
                        if !end_line.starts_with("out: ") {
                            return Some(Err(PunchClockError::CorruptedTimeSheet));
                        }
                        parse_time(&end_line[5..])
                    },
                };
                Some(Ok((start, end)))
            },
            _ => unreachable!() // (None, Some(l)) should not happen
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}

fn parse_time(s: &str) -> Tm {
    strptime(&s[..s.len() - 1], "%a, %d %b %Y %T %Z").unwrap()
}

fn same_day(t1: &Tm, t2: &Tm) -> bool {
    t1.tm_year == t2.tm_year &&
    t1.tm_mon == t2.tm_mon &&
    t1.tm_mday == t2.tm_mday
}

fn print_time_worked(t: &Duration, day: &Tm) {
    println!("{}: {:>2}:{:02}",
        day.strftime("%a, %d %b %Y").unwrap(),
        t.num_hours() ,
        t.num_minutes() % 60
    );
}
<commit_msg>rustup<commit_after>#![feature(io, std_misc, path_ext, file_path, exit_status)]

extern crate time;

use std::fs::{File, create_dir, OpenOptions, remove_file};
use std::io::{Seek, SeekFrom, BufReader, BufRead, Lines, Write};
use std::io;
use std::path::{Path, PathBuf};
use std::fs::PathExt;
use std::env::{args, home_dir, set_exit_status};
use std::fmt;
use std::error::FromError;
use std::time::Duration;
use time::{now_utc, Tm, empty_tm, strptime};

fn main() {
    let result = match args().nth(1) {
        None => Err(PunchClockError::NoCommandGiven),
        Some(command) => {
            let mut time_clock = TimeClock::new().unwrap();
            match &command[..] {
                "in" => time_clock.punch_in(),
                "out" => time_clock.punch_out(),
                "status" => time_clock.status(),
                "report" => time_clock.report_daily_hours(),
                _ => Err(PunchClockError::UnknownCommand)
            }
        }
    };

    if let Err(e) = result {
        println!("Error: {}", e);
        set_exit_status(1);
    }
}

#[derive(Debug)]
enum PunchClockError {
    NoCommandGiven,
    UnknownCommand,
    AlreadyPunchedIn,
    AlreadyPunchedOut,
    CorruptedTimeSheet,
    IoError(io::Error),
}

impl fmt::Display for PunchClockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use PunchClockError::*;
        fmt.write_str(
            match *self {
                NoCommandGiven => "No command given",
                UnknownCommand => "Unknown command",
                AlreadyPunchedIn => "You are already punched in",
                AlreadyPunchedOut => "You're not currently punched in",
                CorruptedTimeSheet => "Bad data in timesheet",
                IoError(_) => "IO error"
            }
        )
    }
}

impl FromError<io::Error> for PunchClockError {
    fn from_error(err: io::Error) -> PunchClockError {
        PunchClockError::IoError(err)
    }
}

type PunchClockResult<T> = Result<T, PunchClockError>;

struct TimeClock {
    now: Tm,
    timesheet: File,
    currently_working: bool,
    state_path: PathBuf
}

impl TimeClock {
    fn new() -> PunchClockResult<TimeClock> {
        let now = now_utc();
        let home = home_dir().unwrap();
        let base_dir = home.join(Path::new(".punch"));
        let timesheet_path = base_dir.join("timesheet");
        let working_state_path = base_dir.join("state");
        if !base_dir.exists() {
            try!(create_dir(&base_dir));
        }
        let timesheet = try!(OpenOptions::new().write(true).append(true)
                            .open(&timesheet_path));
        Ok(TimeClock {
            timesheet: timesheet,
            currently_working: working_state_path.exists(),
            state_path: working_state_path,
            now: now
        })
    }

    // commands

    fn punch_in(&mut self) -> PunchClockResult<()> {
        if self.currently_working {
            return Err(PunchClockError::AlreadyPunchedIn);
        }
        try!(self.timesheet.seek(SeekFrom::End(0)));
        writeln!(&mut self.timesheet, "in: {}", self.now.rfc822()).unwrap();
        self.set_current_working_state(true);
        Ok(())
    }

    fn punch_out(&mut self) -> PunchClockResult<()> {
        if !self.currently_working {
            return Err(PunchClockError::AlreadyPunchedOut);
        }
        try!(self.timesheet.seek(SeekFrom::End(0)));
        try!(writeln!(&mut self.timesheet, "out: {}", self.now.rfc822()));
        self.set_current_working_state(false);
        Ok(())
    }

    fn status(&self) -> PunchClockResult<()> {
        if self.currently_working {
            println!("You're punched in");
        } else {
            println!("You're punched out");
        }
        Ok(())
    }

    fn report_daily_hours(&mut self) -> PunchClockResult<()> {
        try!(self.timesheet.seek(SeekFrom::Start(0)));
        let buf = BufReader::new(try!(File::open(self.timesheet.path().unwrap())));
        let mut current_day = empty_tm();
        let mut time_worked_today = Duration::zero();

        for interval in IntervalIter::from_lines(buf.lines()) {
            let (start, end) = try!(interval);
            if !same_day(&start, &current_day) {
                if !time_worked_today.is_zero() {
                    print_time_worked(&time_worked_today, &current_day);
                }
                current_day = start;
                time_worked_today = Duration::zero();
            }
            time_worked_today =
                time_worked_today + (end.to_timespec() - start.to_timespec());
        }

        if !time_worked_today.is_zero() {
            print_time_worked(&time_worked_today, &current_day);
        }
        Ok(())
    }

    // aux. methods

    fn set_current_working_state(&mut self, currently_working: bool) {
        self.currently_working = currently_working;
        if currently_working {
            File::create(&self.state_path).unwrap();
        } else {
            remove_file(&self.state_path).unwrap();
        }
    }
}

struct IntervalIter {
    lines: Lines<BufReader<File>>
}

impl IntervalIter {
    fn from_lines(lines: Lines<BufReader<File>>) -> IntervalIter {
        IntervalIter {lines: lines}
    }
}

impl Iterator for IntervalIter {
    type Item = PunchClockResult<(Tm, Tm)>;
    fn next(&mut self) -> Option<PunchClockResult<(Tm, Tm)>> {

        // helper function to make error handling a bit nicer
        fn inner_unwrap<T>(x: Option<io::Result<T>>)
                -> PunchClockResult<Option<T>> {
            match x {
                None => Ok(None),
                Some(Ok(inner)) => Ok(Some(inner)),
                Some(Err(e)) => Err(PunchClockError::IoError(e))
            }
        }

        let line_1 = match inner_unwrap(self.lines.next()) {
            Ok(l) => l,
            Err(e) => return Some(Err(e))
        };
        let line_2 = match inner_unwrap(self.lines.next()) {
            Ok(l) => l,
            Err(e) => return Some(Err(e))
        };

        match (line_1, line_2) {
            (None, None) => None,
            (Some(start_line), o_end_line) => {
                if !start_line.starts_with("in: ") {
                    return Some(Err(PunchClockError::CorruptedTimeSheet));
                }
                let start = parse_time(&start_line[4..]);
                let end = match o_end_line {
                    None => now_utc(),
                    Some(end_line) => {
                        if !end_line.starts_with("out: ") {
                            return Some(Err(PunchClockError::CorruptedTimeSheet));
                        }
                        parse_time(&end_line[5..])
                    },
                };
                Some(Ok((start, end)))
            },
            _ => unreachable!() // (None, Some(l)) should not happen
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}

fn parse_time(s: &str) -> Tm {
    strptime(&s[..s.len() - 1], "%a, %d %b %Y %T %Z").unwrap()
}

fn same_day(t1: &Tm, t2: &Tm) -> bool {
    t1.tm_year == t2.tm_year &&
    t1.tm_mon == t2.tm_mon &&
    t1.tm_mday == t2.tm_mday
}

fn print_time_worked(t: &Duration, day: &Tm) {
    println!("{}: {:>2}:{:02}",
        day.strftime("%a, %d %b %Y").unwrap(),
        t.num_hours() ,
        t.num_minutes() % 60
    );
}
<|endoftext|>


<commit_before>extern crate classreader;

use classreader::*;
use std::env;

fn main() {
    env::args().nth(1).expect("usage: javamoose <class or jar file>...");
    let mut args = env::args();
    args.next(); // Skip exe name
    for f in args {
        if f.ends_with("class") {
            process_class_file(&f);
        } else if f.ends_with("jar") {
        } else {
            println!("Ignoring unknown file type {}", f);
        }

    }
    println!("Done!");
}

fn process_class_file(file_name: &String) {
    println!("Loading class file {}", file_name);
    println!("======================================================");
    let class = ClassReader::new_from_path(&file_name).unwrap();
    process_class(&class);
}

fn process_class(class: &Class) {
    assert_eq!(0xCAFEBABE, class.magic);
    println!("class: {}", get_class_name(&class));
    println!("method count: {}", class.methods.len());
    println!("field count:  {}", class.fields.len());
    println!("code size:    {}", get_total_code_size(&class));
    for method in &class.methods {
        println!("\tmethod: {}{}", get_string(&class, method.name_index as usize), get_string(&class, method.descriptor_index as usize));
        println!("\t\tsize:       {}", get_method_size(&method));
        println!("\t\tlines:      {}", get_method_lines(&method));
        println!("\t\tcomplexity: {}", get_method_complexity(&method));
    }

    println!("======================================================");
}

/// Get constant from a pool, correcting for java's 1-based indexes.
fn get_const(class: &Class, i: usize) -> &ConstantPoolInfo {
    &class.constant_pool[i - 1]
}

/// Get string from constant pool
fn get_string(class: &Class, index: usize) -> String {
    match get_const(class, index) {
        &ConstantPoolInfo::Utf8(ref s) => s.clone(),
        _ => "?".to_string()
    }
}

fn get_class_name(class: &Class) -> String {
    match get_const(class, class.this_class as usize) {
        &ConstantPoolInfo::Class(index) => get_string(class, index as usize),
        _ => "?".to_string()
    }
}

fn get_total_code_size(class: &Class) -> usize {
    class.methods.iter().fold(0usize, |sum, method| sum + get_method_size(method))
}

/// Compute method size in byte code instructions
/// If multiple code segments are present in a method (not a javac output) sum it up
fn get_method_size(method: &Method) -> usize {
    method.attributes.iter().fold(0usize, |sum, a| sum + match a {
            &Attribute::Code{ref code, ..} => code.len(),
            _ => 0
        })
}

/// Compute method size in lines of code.
/// If multiple code segments or multiple line number attrbitues are present in a method (not a javac output) sum it up
fn get_method_lines(method: &Method) -> u16 {
    method.attributes.iter().fold(0, |sum, a| sum + match a {
            &Attribute::Code{ref attributes, ..} => attributes.iter().fold(0, |sum, a| sum + match a {
                &Attribute::LineNumberTable(ref line_table) => get_opt_line_number(line_table.last()) - get_opt_line_number(line_table.first()),
                _ => 0
            }),
            _ => 0
        })

}

fn get_opt_line_number(line: Option<&LineNumber>) -> u16 {
    line.map(|x| x.line_number).unwrap_or(0)
}

fn get_method_complexity(method: &Method) -> u16 {
    method.attributes.iter().fold(0, |sum, a| sum + match a {
            &Attribute::Code{ref code, ..} => get_code_complexity(code),
            _ => 0
        })
}

/// Using complexity definition from http://www.leepoint.net/principles_and_practices/complexity/complexity-java-method.html
/// Start with 1 for the method. Add one for each of the following flow-related elements that are found in the method.
/// Returns     Each return that isn't the last statement of a method.
/// Selection   if, else, case, default.
/// Loops   for, while, do-while, break, and continue.
/// Operators   &&, ||, ?, and :
/// Exceptions  catch, finally, throw, or throws clause.
/// Bytecode reference: http://www.angelibrary.com/computer/java_21days/ch32.htm
fn get_code_complexity(code: &Vec<(u32, Instruction)>) -> u16 {
    // println!("{:?}", code);
    // We start from zero to account for always-present final return - it will add the "starting" 1 for us.
    code.iter().fold(0, |sum, instruction| sum + match instruction.1 {
        Instruction::areturn => 1,
        Instruction::athrow => 1,
        Instruction::dreturn => 1,
        Instruction::freturn => 1,
        Instruction::if_acmpeq(..) => 1,
        Instruction::if_acmpne(..) => 1,
        Instruction::if_icmpeq(..) => 1,
        Instruction::if_icmpne(..) => 1,
        Instruction::if_icmplt(..) => 1,
        Instruction::if_icmpge(..) => 1,
        Instruction::if_icmpgt(..) => 1,
        Instruction::if_icmple(..) => 1,
        Instruction::ifeq(..) => 1,
        Instruction::ifne(..) => 1,
        Instruction::iflt(..) => 1,
        Instruction::ifge(..) => 1,
        Instruction::ifgt(..) => 1,
        Instruction::ifle(..) => 1,
        Instruction::ifnonnull(..) => 1,
        Instruction::ifnull(..) => 1,
        Instruction::ireturn => 1,
        Instruction::lookupswitch(_, ref jumps) => jumps.len() as u16, // tricky - lets use the size of the jump table
        Instruction::lreturn => 1,
        Instruction::return_ => 1,
        Instruction::tableswitch(_, _, ref jumps) => jumps.len() as u16, // tricky - lets use the size of the jump table
        // Subroutines in the method. Currently - do not count them towards the complexity. They are used to compile "finally", but I do not see them as branching really. Finally block is executed every time
        // Instruction::jsr(..) => 1,
        // Instruction::jsr_w(..) => 1,
        // Instruction::ret => 1,
        // Instruction::ret_w => 1,
        _ => 0
    })
}

<commit_msg>Added jar support<commit_after>extern crate classreader;
extern crate zip;

use classreader::*;
use std::env;
use std::fs::File;

fn main() {
    env::args().nth(1).expect("usage: javamoose <class or jar file>...");
    let mut args = env::args();
    args.next(); // Skip exe name
    for f in args {
        if f.ends_with("class") {
            process_class_file(&f);
        } else if f.ends_with("jar") {
            process_jar_file(&f);
        } else {
            println!("Ignoring unknown file type {}", f);
        }

    }
    println!("Done!");
}

fn process_class_file(file_name: &String) {
    println!("Loading class file {}", file_name);
    println!("======================================================");
    let class = ClassReader::new_from_path(&file_name).unwrap();
    process_class(&class);
}

fn process_jar_file(file_name: &String) {
    let file = File::open(file_name).expect("couldn't find a file!");
    let mut zip = zip::ZipArchive::new(file).expect("could not read JAR");
    for i in 0..zip.len() {
        let mut class_file = zip.by_index(i).unwrap();
        if class_file.name().ends_with("class") {
            println!("Reading {}", class_file.name());
            let class = ClassReader::new_from_reader(&mut class_file).unwrap();
            process_class(&class);
        }
    }
}

fn process_class(class: &Class) {
    assert_eq!(0xCAFEBABE, class.magic);
    println!("class: {}", get_class_name(&class));
    println!("method count: {}", class.methods.len());
    println!("field count:  {}", class.fields.len());
    println!("code size:    {}", get_total_code_size(&class));
    for method in &class.methods {
        println!("\tmethod: {}{}", get_string(&class, method.name_index as usize), get_string(&class, method.descriptor_index as usize));
        println!("\t\tsize:       {}", get_method_size(&method));
        println!("\t\tlines:      {}", get_method_lines(&method));
        println!("\t\tcomplexity: {}", get_method_complexity(&method));
    }

    println!("======================================================");
}

/// Get constant from a pool, correcting for java's 1-based indexes.
fn get_const(class: &Class, i: usize) -> &ConstantPoolInfo {
    &class.constant_pool[i - 1]
}

/// Get string from constant pool
fn get_string(class: &Class, index: usize) -> String {
    match get_const(class, index) {
        &ConstantPoolInfo::Utf8(ref s) => s.clone(),
        _ => "?".to_string()
    }
}

fn get_class_name(class: &Class) -> String {
    match get_const(class, class.this_class as usize) {
        &ConstantPoolInfo::Class(index) => get_string(class, index as usize),
        _ => "?".to_string()
    }
}

fn get_total_code_size(class: &Class) -> usize {
    class.methods.iter().fold(0usize, |sum, method| sum + get_method_size(method))
}

/// Compute method size in byte code instructions
/// If multiple code segments are present in a method (not a javac output) sum it up
fn get_method_size(method: &Method) -> usize {
    method.attributes.iter().fold(0usize, |sum, a| sum + match a {
            &Attribute::Code{ref code, ..} => code.len(),
            _ => 0
        })
}

/// Compute method size in lines of code.
/// If multiple code segments or multiple line number attrbitues are present in a method (not a javac output) sum it up
fn get_method_lines(method: &Method) -> u16 {
    method.attributes.iter().fold(0, |sum, a| sum + match a {
            &Attribute::Code{ref attributes, ..} => attributes.iter().fold(0, |sum, a| sum + match a {
                &Attribute::LineNumberTable(ref line_table) => get_opt_line_number(line_table.last()) - get_opt_line_number(line_table.first()),
                _ => 0
            }),
            _ => 0
        })

}

fn get_opt_line_number(line: Option<&LineNumber>) -> u16 {
    line.map(|x| x.line_number).unwrap_or(0)
}

fn get_method_complexity(method: &Method) -> u16 {
    method.attributes.iter().fold(0, |sum, a| sum + match a {
            &Attribute::Code{ref code, ..} => get_code_complexity(code),
            _ => 0
        })
}

/// Using complexity definition from http://www.leepoint.net/principles_and_practices/complexity/complexity-java-method.html
/// Start with 1 for the method. Add one for each of the following flow-related elements that are found in the method.
/// Returns     Each return that isn't the last statement of a method.
/// Selection   if, else, case, default.
/// Loops   for, while, do-while, break, and continue.
/// Operators   &&, ||, ?, and :
/// Exceptions  catch, finally, throw, or throws clause.
/// Bytecode reference: http://www.angelibrary.com/computer/java_21days/ch32.htm
fn get_code_complexity(code: &Vec<(u32, Instruction)>) -> u16 {
    // println!("{:?}", code);
    // We start from zero to account for always-present final return - it will add the "starting" 1 for us.
    code.iter().fold(0, |sum, instruction| sum + match instruction.1 {
        Instruction::areturn => 1,
        Instruction::athrow => 1,
        Instruction::dreturn => 1,
        Instruction::freturn => 1,
        Instruction::if_acmpeq(..) => 1,
        Instruction::if_acmpne(..) => 1,
        Instruction::if_icmpeq(..) => 1,
        Instruction::if_icmpne(..) => 1,
        Instruction::if_icmplt(..) => 1,
        Instruction::if_icmpge(..) => 1,
        Instruction::if_icmpgt(..) => 1,
        Instruction::if_icmple(..) => 1,
        Instruction::ifeq(..) => 1,
        Instruction::ifne(..) => 1,
        Instruction::iflt(..) => 1,
        Instruction::ifge(..) => 1,
        Instruction::ifgt(..) => 1,
        Instruction::ifle(..) => 1,
        Instruction::ifnonnull(..) => 1,
        Instruction::ifnull(..) => 1,
        Instruction::ireturn => 1,
        Instruction::lookupswitch(_, ref jumps) => jumps.len() as u16, // tricky - lets use the size of the jump table
        Instruction::lreturn => 1,
        Instruction::return_ => 1,
        Instruction::tableswitch(_, _, ref jumps) => jumps.len() as u16, // tricky - lets use the size of the jump table
        // Subroutines in the method. Currently - do not count them towards the complexity. They are used to compile "finally", but I do not see them as branching really. Finally block is executed every time
        // Instruction::jsr(..) => 1,
        // Instruction::jsr_w(..) => 1,
        // Instruction::ret => 1,
        // Instruction::ret_w => 1,
        _ => 0
    })
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

/* automatically generated by rust-bindgen */

use libc;
use jsapi::*;
use jsfriendapi::JSJitInfo;
use jsval::JSVal;

pub static JS_STRUCTURED_CLONE_VERSION: u32 = 1;

pub struct ProxyTraps {
    pub getPropertyDescriptor: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, bool, *mut JSPropertyDescriptor) -> bool>,
    pub getOwnPropertyDescriptor: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, bool, *mut JSPropertyDescriptor) -> bool>,
    pub defineProperty: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut JSPropertyDescriptor) -> bool>,
    pub getOwnPropertyNames: *const u8, //XXX need a representation for AutoIdVector&
    pub delete_: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub enumerate: *const u8, //XXX need a representation for AutoIdVector&

    pub has: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub hasOwn: Option<extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub get: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, jsid, *mut JSVal) -> bool>,
    pub set: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, jsid, bool, *mut JSVal) -> bool>,
    pub keys: *const u8, //XXX need a representation for AutoIdVector&
    pub iterate: Option<extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>,

    pub call: Option<extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>,
    pub construct: Option<extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal, *mut JSVal) -> bool>,
    pub nativeCall: *const u8, //XXX need a representation for IsAcceptableThis, NativeImpl, and CallArgs
    pub hasInstance: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut JSVal, *mut bool) -> bool>,
    pub typeOf: Option<extern "C" fn(*mut JSContext, *mut JSObject) -> uint>, //XXX JSType enum
    pub objectClassIs: Option<extern "C" fn(*mut JSObject, uint, *mut JSContext) -> bool>, //XXX ESClassValue enum
    pub obj_toString: Option<extern "C" fn(*mut JSContext, *mut JSObject) -> *mut JSString>,
    pub fun_toString: Option<extern "C" fn(*mut JSContext, *mut JSObject, uint) -> *mut JSString>,
    //regexp_toShared: *u8,
    pub defaultValue: Option<extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>, //XXX JSType enum
    pub iteratorNext: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut JSVal) -> bool>,
    pub finalize: Option<extern "C" fn(*mut JSFreeOp, *mut JSObject)>,
    pub getElementIfPresent: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, u32, *mut JSVal, *mut bool) -> bool>,
    pub getPrototypeOf: Option<extern "C" fn(*mut JSContext, *mut JSObject, *mut *mut JSObject) -> bool>,
    pub trace: Option<extern "C" fn(*mut JSTracer, *mut JSObject)>,
}

#[link(name = "jsglue")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "stdc++")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern { }

extern {

//#[rust_stack]
pub fn RUST_JS_NumberValue(d: f64) -> JSVal;

//#[rust_stack]
pub fn CallJitPropertyOp(info: *const JSJitInfo, cx: *mut JSContext, thisObj: *mut JSObject, specializedThis: *mut libc::c_void, vp: *mut JSVal) -> JSBool;

//#[rust_stack]
pub fn CallJitMethodOp(info: *const JSJitInfo, cx: *mut JSContext, thisObj: *mut JSObject, specializedThis: *mut libc::c_void, argc: libc::c_uint, vp: *mut JSVal) -> JSBool;

//#[rust_stack]
pub fn RUST_FUNCTION_VALUE_TO_JITINFO(v: JSVal) -> *const JSJitInfo;

pub fn SetFunctionNativeReserved(fun: *mut JSObject, which: libc::size_t, val: *mut JSVal);
pub fn GetFunctionNativeReserved(fun: *mut JSObject, which: libc::size_t) -> *mut JSVal;

pub fn CreateProxyHandler(traps: *const ProxyTraps, extra: *const libc::c_void) -> *const libc::c_void;
pub fn CreateWrapperProxyHandler(traps: *const ProxyTraps) -> *const libc::c_void;
pub fn NewProxyObject(cx: *mut JSContext, handler: *const libc::c_void, priv_: *const JSVal,
                      proto: *mut JSObject, parent: *mut JSObject, call: *mut JSObject,
                      construct: *mut JSObject) -> *mut JSObject;
pub fn WrapperNew(cx: *mut JSContext, parent: *mut JSObject, handler: *const libc::c_void) -> *mut JSObject;

pub fn GetProxyExtra(obj: *mut JSObject, slot: libc::c_uint) -> JSVal;
pub fn GetProxyPrivate(obj: *mut JSObject) -> JSVal;
pub fn SetProxyExtra(obj: *mut JSObject, slot: libc::c_uint, val: JSVal);

pub fn GetObjectProto(obj: *mut JSObject) -> *mut JSObject;
pub fn GetObjectParent(obj: *mut JSObject) -> *mut JSObject;

pub fn RUST_JSID_IS_INT(id: jsid) -> JSBool;
pub fn RUST_JSID_TO_INT(id: jsid) -> libc::c_int;
pub fn RUST_JSID_IS_STRING(id: jsid) -> JSBool;
pub fn RUST_JSID_TO_STRING(id: jsid) -> *mut JSString;

pub fn RUST_SET_JITINFO(func: *mut JSFunction, info: *const JSJitInfo);

pub fn RUST_INTERNED_STRING_TO_JSID(cx: *mut JSContext, str: *mut JSString) -> jsid;

pub fn DefineFunctionWithReserved(cx: *mut JSContext, obj: *mut JSObject,
                                  name: *const libc::c_char, call: JSNative, nargs: libc::c_uint,
                                  attrs: libc::c_uint) -> *mut JSObject;
pub fn GetObjectJSClass(obj: *mut JSObject) -> *mut JSClass;
pub fn RUST_js_GetErrorMessage(userRef: *mut libc::c_void, locale: *const libc::c_char,
                               errorNumber: libc::c_uint) -> *const JSErrorFormatString;
pub fn js_IsObjectProxyClass(obj: *mut JSObject) -> bool;
pub fn js_IsFunctionProxyClass(obj: *mut JSObject) -> bool;
pub fn IsProxyHandlerFamily(obj: *mut JSObject) -> bool;
pub fn GetProxyHandlerExtra(obj: *mut JSObject) -> *const libc::c_void;
pub fn GetProxyHandler(obj: *mut JSObject) -> *mut libc::c_void;
pub fn InvokeGetOwnPropertyDescriptor(handler: *mut libc::c_void, cx: *mut JSContext, proxy: *mut JSObject, id: jsid, set: bool, desc: *mut JSPropertyDescriptor) -> bool;
pub fn GetGlobalForObjectCrossCompartment(obj: *mut JSObject) -> *mut JSObject;
pub fn ReportError(cx: *mut JSContext, error: *const libc::c_char);
pub fn IsWrapper(obj: *mut JSObject) -> JSBool;
pub fn UnwrapObject(obj: *mut JSObject, stopAtOuter: JSBool, flags: *mut libc::c_uint) -> *mut JSObject;
}
<commit_msg>Store unsafe fns in ProxyTraps fields<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

/* automatically generated by rust-bindgen */

use libc;
use jsapi::*;
use jsfriendapi::JSJitInfo;
use jsval::JSVal;

pub static JS_STRUCTURED_CLONE_VERSION: u32 = 1;

pub struct ProxyTraps {
    pub getPropertyDescriptor: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, bool, *mut JSPropertyDescriptor) -> bool>,
    pub getOwnPropertyDescriptor: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, bool, *mut JSPropertyDescriptor) -> bool>,
    pub defineProperty: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut JSPropertyDescriptor) -> bool>,
    pub getOwnPropertyNames: *const u8, //XXX need a representation for AutoIdVector&
    pub delete_: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub enumerate: *const u8, //XXX need a representation for AutoIdVector&

    pub has: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub hasOwn: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool>,
    pub get: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, jsid, *mut JSVal) -> bool>,
    pub set: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, jsid, bool, *mut JSVal) -> bool>,
    pub keys: *const u8, //XXX need a representation for AutoIdVector&
    pub iterate: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>,

    pub call: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>,
    pub construct: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal, *mut JSVal) -> bool>,
    pub nativeCall: *const u8, //XXX need a representation for IsAcceptableThis, NativeImpl, and CallArgs
    pub hasInstance: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSVal, *mut bool) -> bool>,
    pub typeOf: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject) -> uint>, //XXX JSType enum
    pub objectClassIs: Option<unsafe extern "C" fn(*mut JSObject, uint, *mut JSContext) -> bool>, //XXX ESClassValue enum
    pub obj_toString: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject) -> *mut JSString>,
    pub fun_toString: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, uint) -> *mut JSString>,
    //regexp_toShared: *u8,
    pub defaultValue: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, uint, *mut JSVal) -> bool>, //XXX JSType enum
    pub iteratorNext: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSVal) -> bool>,
    pub finalize: Option<unsafe extern "C" fn(*mut JSFreeOp, *mut JSObject)>,
    pub getElementIfPresent: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, u32, *mut JSVal, *mut bool) -> bool>,
    pub getPrototypeOf: Option<unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut *mut JSObject) -> bool>,
    pub trace: Option<unsafe extern "C" fn(*mut JSTracer, *mut JSObject)>,
}

#[link(name = "jsglue")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "stdc++")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern { }

extern {

//#[rust_stack]
pub fn RUST_JS_NumberValue(d: f64) -> JSVal;

//#[rust_stack]
pub fn CallJitPropertyOp(info: *const JSJitInfo, cx: *mut JSContext, thisObj: *mut JSObject, specializedThis: *mut libc::c_void, vp: *mut JSVal) -> JSBool;

//#[rust_stack]
pub fn CallJitMethodOp(info: *const JSJitInfo, cx: *mut JSContext, thisObj: *mut JSObject, specializedThis: *mut libc::c_void, argc: libc::c_uint, vp: *mut JSVal) -> JSBool;

//#[rust_stack]
pub fn RUST_FUNCTION_VALUE_TO_JITINFO(v: JSVal) -> *const JSJitInfo;

pub fn SetFunctionNativeReserved(fun: *mut JSObject, which: libc::size_t, val: *mut JSVal);
pub fn GetFunctionNativeReserved(fun: *mut JSObject, which: libc::size_t) -> *mut JSVal;

pub fn CreateProxyHandler(traps: *const ProxyTraps, extra: *const libc::c_void) -> *const libc::c_void;
pub fn CreateWrapperProxyHandler(traps: *const ProxyTraps) -> *const libc::c_void;
pub fn NewProxyObject(cx: *mut JSContext, handler: *const libc::c_void, priv_: *const JSVal,
                      proto: *mut JSObject, parent: *mut JSObject, call: *mut JSObject,
                      construct: *mut JSObject) -> *mut JSObject;
pub fn WrapperNew(cx: *mut JSContext, parent: *mut JSObject, handler: *const libc::c_void) -> *mut JSObject;

pub fn GetProxyExtra(obj: *mut JSObject, slot: libc::c_uint) -> JSVal;
pub fn GetProxyPrivate(obj: *mut JSObject) -> JSVal;
pub fn SetProxyExtra(obj: *mut JSObject, slot: libc::c_uint, val: JSVal);

pub fn GetObjectProto(obj: *mut JSObject) -> *mut JSObject;
pub fn GetObjectParent(obj: *mut JSObject) -> *mut JSObject;

pub fn RUST_JSID_IS_INT(id: jsid) -> JSBool;
pub fn RUST_JSID_TO_INT(id: jsid) -> libc::c_int;
pub fn RUST_JSID_IS_STRING(id: jsid) -> JSBool;
pub fn RUST_JSID_TO_STRING(id: jsid) -> *mut JSString;

pub fn RUST_SET_JITINFO(func: *mut JSFunction, info: *const JSJitInfo);

pub fn RUST_INTERNED_STRING_TO_JSID(cx: *mut JSContext, str: *mut JSString) -> jsid;

pub fn DefineFunctionWithReserved(cx: *mut JSContext, obj: *mut JSObject,
                                  name: *const libc::c_char, call: JSNative, nargs: libc::c_uint,
                                  attrs: libc::c_uint) -> *mut JSObject;
pub fn GetObjectJSClass(obj: *mut JSObject) -> *mut JSClass;
pub fn RUST_js_GetErrorMessage(userRef: *mut libc::c_void, locale: *const libc::c_char,
                               errorNumber: libc::c_uint) -> *const JSErrorFormatString;
pub fn js_IsObjectProxyClass(obj: *mut JSObject) -> bool;
pub fn js_IsFunctionProxyClass(obj: *mut JSObject) -> bool;
pub fn IsProxyHandlerFamily(obj: *mut JSObject) -> bool;
pub fn GetProxyHandlerExtra(obj: *mut JSObject) -> *const libc::c_void;
pub fn GetProxyHandler(obj: *mut JSObject) -> *mut libc::c_void;
pub fn InvokeGetOwnPropertyDescriptor(handler: *mut libc::c_void, cx: *mut JSContext, proxy: *mut JSObject, id: jsid, set: bool, desc: *mut JSPropertyDescriptor) -> bool;
pub fn GetGlobalForObjectCrossCompartment(obj: *mut JSObject) -> *mut JSObject;
pub fn ReportError(cx: *mut JSContext, error: *const libc::c_char);
pub fn IsWrapper(obj: *mut JSObject) -> JSBool;
pub fn UnwrapObject(obj: *mut JSObject, stopAtOuter: JSBool, flags: *mut libc::c_uint) -> *mut JSObject;
}
<|endoftext|>


<commit_before>// Based on smallpt, http://www.kevinbeason.com/smallpt/ which is also licensed under
// the MIT license.
use std::fs::File;
use std::io::BufWriter;
use std::io;
use std::io::prelude::*;
use std::sync::Arc;
use std::sync::mpsc::channel;

extern crate rand;
use rand::{Rng, XorShiftRng, SeedableRng};

extern crate threadpool;
use threadpool::ThreadPool;

extern crate num_cpus;

extern crate argparse;
use argparse::{ArgumentParser, Store};

mod path_tracer;
use path_tracer::*;

enum Material {
    Diffuse,
    Specular,
    Refractive
}

struct Sphere {
    material: Material,
    radius: f64,
    position: Vec3d,
    emission: Vec3d,
    colour: Vec3d
}

impl Sphere {
    fn new(material: Material, radius: f64, position: Vec3d, emission: Vec3d, colour: Vec3d) -> Sphere {
        Sphere {
          material: material,
          radius: radius,
          position: position,
          emission: emission,
          colour: colour
        }
    }
    fn intersect(&self, ray: &Ray) -> Option<f64> {
        let op = self.position - ray.origin;
        let b = op.dot(ray.direction);
        let determinant = b * b - op.dot(op) + self.radius * self.radius;
        if determinant < 0.0 { return None; }
        let determinant = determinant.sqrt();
        let t1 = b - determinant;
        let t2 = b + determinant;
        const EPSILON : f64 = 0.0001;
        if t1 > EPSILON {
            Some(t1)
        } else if t2 > EPSILON {
            Some(t2)
        } else {
            None
        }
    }
}

#[test]
fn intersection() {
    let sphere = Sphere::new(
        Material::Diffuse,
        100.0,
        Vec3d::new(0.0, 0.0, 200.0),
        Vec3d::zero(),
        Vec3d::zero());
    let ray = Ray::new(Vec3d::zero(), Vec3d::new(0.0, 0.0, 1.0));
    match sphere.intersect(&ray) {
        Some(x) => assert_eq!(x, 100.0),
        None => panic!("unexpected")
    }
    let ray = Ray::new(Vec3d::zero(), Vec3d::new(0.0, 1.0, 0.0));
    match sphere.intersect(&ray) {
        Some(_) => panic!("unexpected"),
        None => {}
    }
}

struct HitRecord<'a> {
    sphere: &'a Sphere,
    dist: f64
}

fn intersect<'a>(scene: &'a [Sphere], ray: &Ray) -> Option<HitRecord<'a>> {
    let mut result : Option<HitRecord<'a>> = None;
    for sph in scene {
        if let Some(dist) = sph.intersect(&ray) {
            if match result { None => true, Some(ref x) => dist < x.dist } {
                result = Some(HitRecord { sphere: &sph, dist: dist });
            }
        }
    }
    result
}

fn radiance<R: Rng>(scene: &[Sphere], ray: &Ray, depth: i32, rng: &mut R) -> Vec3d {
    if let Some(hit) = intersect(&scene, &ray) {
        let hit_pos = ray.origin + ray.direction * hit.dist;
        let hit_normal = (hit_pos - hit.sphere.position).normalized();
        let n1 = if hit_normal.dot(ray.direction) < 0.0 { hit_normal } else { hit_normal.neg() };
        let mut colour = hit.sphere.colour;
        let max_reflectance = colour.max_component();
        let depth = depth + 1;
        if depth > 5 {
            let rand = rng.gen::<f64>();
            if rand < max_reflectance && depth < 500 { // Rust's stack blows up ~600 on my machine
               colour = colour * (1.0 / max_reflectance);
            } else {
                return hit.sphere.emission;
            }
        }
        match hit.sphere.material {
            Material::Diffuse => {
                // Get a random polar coordinate
                let r1 = rng.gen::<f64>() * 2.0 * std::f64::consts::PI;
                let r2 = rng.gen::<f64>();
                let r2s = r2.sqrt();
                // Create a coordinate system u,v,w local to the point, where the w is the normal
                // pointing out of the sphere and the u and v are orthonormal to w.
                let w = n1;
                // Pick an arbitrary non-zero preferred axis for u
                let u = if n1.x.abs() > 0.1 { Vec3d::new(0.0, 1.0, 0.0) } else { Vec3d::new(1.0, 0.0, 0.0) }.cross(w);
                let v = w.cross(u);
                // construct the new direction
                let new_dir = u * r1.cos() * r2s + v * r1.sin() * r2s + w * (1.0 - r2).sqrt();
                colour = colour * radiance(scene, &Ray::new(hit_pos, new_dir.normalized()), depth, rng);
            },
            Material::Specular => {
                let reflection = ray.direction - hit_normal * 2.0 * hit_normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit_pos, reflection);
                colour = colour * radiance(scene, &reflected_ray, depth, rng);
            },
            Material::Refractive => {
                let reflection = ray.direction - hit_normal * 2.0 * hit_normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit_pos, reflection);
                let into = if hit_normal.dot(n1) > 0.0 { true } else { false };
                let nc = 1.0;
                let nt = 1.5;
                let nnt = if into { nc/nt } else { nt/nc };
                let ddn = ray.direction.dot(n1);
                let cos2t = 1.0 - nnt * nnt * (1.0 - ddn * ddn);
                if cos2t < 0.0 {
                    // Total internal reflection
                    colour = colour * radiance(scene, &reflected_ray, depth, rng);
                } else {
                    let tbd = ddn * nnt + cos2t.sqrt();
                    let tbd = if into { tbd } else { -tbd };
                    let tdir = (ray.direction * nnt - hit_normal * tbd).normalized();
                    let transmitted_ray = Ray::new(hit_pos, tdir);
                    let a = nt - nc;
                    let b = nt + nc;
                    let r0 = (a * a) / (b * b);
                    let c = 1.0 - if into { -ddn } else { tdir.dot(hit_normal) };
                    let re = r0 + (1.0 - r0) * c * c * c * c * c;
                    let tr = 1.0 - re;
                    let p = 0.25 + 0.5 * re;
                    let rp = re / p;
                    let tp = tr / (1.0 - p);
                    colour = colour * if depth > 2 {
                        if rng.gen::<f64>() < p {
                            radiance(scene, &reflected_ray, depth, rng) * rp
                        } else {
                            radiance(scene, &transmitted_ray, depth, rng) * tp
                        }
                    } else {
                        radiance(scene, &reflected_ray, depth, rng) * re +
                            radiance(scene, &transmitted_ray, depth, rng) * tr
                    }
                }
            }
        }
        hit.sphere.emission + colour
    } else {
        Vec3d::zero()
    }
}

fn random_samp<T: Rng>(rng: &mut T) -> f64 {
    let r = 2.0 * rng.gen::<f64>();
    if r < 1.0 { r.sqrt() - 1.0 } else { 1.0 - (2.0 - r).sqrt() }
}

fn to_int(v: f64) -> u8 {
    let ch = (v.powf(1.0/2.2) * 255.0 + 0.5) as i64;
    if ch < 0 { 0 } else if ch > 255 { 255 } else { ch as u8 }
}

fn main() {
    let mut samps = 1;
    let mut width = 1024;
    let mut height = 768;
    let mut output_filename = "image.ppm".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Render a simple image");
        ap.refer(&mut samps).add_option(&["-s", "--samples"], Store, "Number of samples");
        ap.refer(&mut height).add_option(&["-h", "--height"], Store, "Height");
        ap.refer(&mut width).add_option(&["-w", "--width"], Store, "Width");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.parse_args_or_exit();
    }
    samps = samps / 4;
    if samps < 1 { samps = 1; }
    const BLACK : Vec3d = Vec3d { x: 0.0, y: 0.0, z: 0.0 };
    const RED : Vec3d = Vec3d { x: 0.75, y: 0.25, z: 0.25 };
    const BLUE : Vec3d = Vec3d { x: 0.25, y: 0.25, z: 0.75 };
    const GREY : Vec3d = Vec3d { x: 0.75, y: 0.75, z: 0.75 };
    const WHITE : Vec3d = Vec3d { x: 0.999, y: 0.999, z: 0.999 };
    let scene = Arc::new(vec!{
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(1e5+1.0, 40.8, 81.6),
            BLACK, RED),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(-1e5+99.0, 40.8, 81.6),
            BLACK, BLUE),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 40.8, 1e5),
            BLACK, GREY),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 40.8, -1e5 + 170.0),
            BLACK, BLACK),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 1e5, 81.6),
            BLACK, GREY),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, -1e5 + 81.6, 81.6),
            BLACK, GREY),
        Sphere::new(Material::Specular, 16.5,
            Vec3d::new(27.0, 16.5, 47.0),
            BLACK, WHITE),
        Sphere::new(Material::Refractive, 16.5,
            Vec3d::new(73.0, 16.5, 78.0),
            BLACK, WHITE),
        Sphere::new(Material::Diffuse, 600.0,
            Vec3d::new(50.0, 681.6 - 0.27, 81.6),
            Vec3d::new(12.0, 12.0, 12.0), BLACK),
    });

    let camera_pos = Vec3d::new(50.0, 52.0, 295.6);
    let camera_dir = Vec3d::new(0.0, -0.042612, -1.0);
    let camera_x = Vec3d::new(width as f64 * 0.5135 / height as f64, 0.0, 0.0);
    let camera_y = camera_x.cross(camera_dir).normalized() * 0.5135;

    let num_threads = num_cpus::get();
    println!("Using {} threads", num_threads);
    let pool = ThreadPool::new(num_threads);
    let (tx, rx) = channel();

    for y in 0..height {
        let tx = tx.clone();
        let scene = scene.clone();
        pool.execute(move || {
            let mut line = Vec::with_capacity(width);
            let mut rng = XorShiftRng::from_seed([1 + (y * y) as u32, 0x193a6754, 0x15aac60d, 0xb017f00d]);
            for x in 0..width {
                let mut sum = Vec3d::zero();
                for sx in 0..2 {
                    for sy in 0..2 {
                        for _samp in 0..samps {
                            let dx = random_samp(&mut rng);
                            let dy = random_samp(&mut rng);
                            let sub_x = (sx as f64 + 0.5 + dx) / 2.0;
                            let dir_x = (sub_x + x as f64) / width as f64 - 0.5;
                            let sub_y = (sy as f64 + 0.5 + dy) / 2.0;
                            let dir_y = (sub_y + (height -y - 1) as f64) / height as f64 - 0.5;
                            let dir = (camera_x * dir_x + camera_y * dir_y + camera_dir).normalized();
                            let jittered_ray = Ray::new(camera_pos + dir * 140.0, dir);
                            let sample = radiance(&scene, &jittered_ray, 0, &mut rng);
                            sum = sum + sample;
                        }
                    }
                }
                line.push((sum / (samps * 4) as f64).clamp());
            }
            tx.send((y, line)).unwrap();
        });
    }
    let mut left = height;
    let mut screen : Vec<Vec<Vec3d>> = Vec::new();
    for _y in 0..height {
        screen.push(Vec::new());
    }
    while left > 0 {
        print!("Rendering ({} spp) {:.4}%...\r", samps * 4, 100.0 * (height - left) as f64 / height as f64);
        io::stdout().flush().ok().expect("Could not flush stdout");
        let (y, line) = rx.recv().unwrap();
        screen[y] = line;
        left -= 1;
    }
    println!("\nWriting output to '{}'", output_filename);
    let output_file = File::create(output_filename).unwrap();
    let mut writer = BufWriter::new(output_file);
    write!(&mut writer, "P3\n{} {}\n255\n", width, height).unwrap();
    for y in 0..height {
        for x in 0..width {
            let sum = screen[y][x];
            write!(&mut writer, "{} {} {} ", to_int(sum.x), to_int(sum.y), to_int(sum.z)).unwrap();
        }
    }
}
<commit_msg>smallpt normalizes camera direction<commit_after>// Based on smallpt, http://www.kevinbeason.com/smallpt/ which is also licensed under
// the MIT license.
use std::fs::File;
use std::io::BufWriter;
use std::io;
use std::io::prelude::*;
use std::sync::Arc;
use std::sync::mpsc::channel;

extern crate rand;
use rand::{Rng, XorShiftRng, SeedableRng};

extern crate threadpool;
use threadpool::ThreadPool;

extern crate num_cpus;

extern crate argparse;
use argparse::{ArgumentParser, Store};

mod path_tracer;
use path_tracer::*;

enum Material {
    Diffuse,
    Specular,
    Refractive
}

struct Sphere {
    material: Material,
    radius: f64,
    position: Vec3d,
    emission: Vec3d,
    colour: Vec3d
}

impl Sphere {
    fn new(material: Material, radius: f64, position: Vec3d, emission: Vec3d, colour: Vec3d) -> Sphere {
        Sphere {
          material: material,
          radius: radius,
          position: position,
          emission: emission,
          colour: colour
        }
    }
    fn intersect(&self, ray: &Ray) -> Option<f64> {
        let op = self.position - ray.origin;
        let b = op.dot(ray.direction);
        let determinant = b * b - op.dot(op) + self.radius * self.radius;
        if determinant < 0.0 { return None; }
        let determinant = determinant.sqrt();
        let t1 = b - determinant;
        let t2 = b + determinant;
        const EPSILON : f64 = 0.0001;
        if t1 > EPSILON {
            Some(t1)
        } else if t2 > EPSILON {
            Some(t2)
        } else {
            None
        }
    }
}

#[test]
fn intersection() {
    let sphere = Sphere::new(
        Material::Diffuse,
        100.0,
        Vec3d::new(0.0, 0.0, 200.0),
        Vec3d::zero(),
        Vec3d::zero());
    let ray = Ray::new(Vec3d::zero(), Vec3d::new(0.0, 0.0, 1.0));
    match sphere.intersect(&ray) {
        Some(x) => assert_eq!(x, 100.0),
        None => panic!("unexpected")
    }
    let ray = Ray::new(Vec3d::zero(), Vec3d::new(0.0, 1.0, 0.0));
    match sphere.intersect(&ray) {
        Some(_) => panic!("unexpected"),
        None => {}
    }
}

struct HitRecord<'a> {
    sphere: &'a Sphere,
    dist: f64
}

fn intersect<'a>(scene: &'a [Sphere], ray: &Ray) -> Option<HitRecord<'a>> {
    let mut result : Option<HitRecord<'a>> = None;
    for sph in scene {
        if let Some(dist) = sph.intersect(&ray) {
            if match result { None => true, Some(ref x) => dist < x.dist } {
                result = Some(HitRecord { sphere: &sph, dist: dist });
            }
        }
    }
    result
}

fn radiance<R: Rng>(scene: &[Sphere], ray: &Ray, depth: i32, rng: &mut R) -> Vec3d {
    if let Some(hit) = intersect(&scene, &ray) {
        let hit_pos = ray.origin + ray.direction * hit.dist;
        let hit_normal = (hit_pos - hit.sphere.position).normalized();
        let n1 = if hit_normal.dot(ray.direction) < 0.0 { hit_normal } else { hit_normal.neg() };
        let mut colour = hit.sphere.colour;
        let max_reflectance = colour.max_component();
        let depth = depth + 1;
        if depth > 5 {
            let rand = rng.gen::<f64>();
            if rand < max_reflectance && depth < 500 { // Rust's stack blows up ~600 on my machine
               colour = colour * (1.0 / max_reflectance);
            } else {
                return hit.sphere.emission;
            }
        }
        match hit.sphere.material {
            Material::Diffuse => {
                // Get a random polar coordinate
                let r1 = rng.gen::<f64>() * 2.0 * std::f64::consts::PI;
                let r2 = rng.gen::<f64>();
                let r2s = r2.sqrt();
                // Create a coordinate system u,v,w local to the point, where the w is the normal
                // pointing out of the sphere and the u and v are orthonormal to w.
                let w = n1;
                // Pick an arbitrary non-zero preferred axis for u
                let u = if n1.x.abs() > 0.1 { Vec3d::new(0.0, 1.0, 0.0) } else { Vec3d::new(1.0, 0.0, 0.0) }.cross(w);
                let v = w.cross(u);
                // construct the new direction
                let new_dir = u * r1.cos() * r2s + v * r1.sin() * r2s + w * (1.0 - r2).sqrt();
                colour = colour * radiance(scene, &Ray::new(hit_pos, new_dir.normalized()), depth, rng);
            },
            Material::Specular => {
                let reflection = ray.direction - hit_normal * 2.0 * hit_normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit_pos, reflection);
                colour = colour * radiance(scene, &reflected_ray, depth, rng);
            },
            Material::Refractive => {
                let reflection = ray.direction - hit_normal * 2.0 * hit_normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit_pos, reflection);
                let into = if hit_normal.dot(n1) > 0.0 { true } else { false };
                let nc = 1.0;
                let nt = 1.5;
                let nnt = if into { nc/nt } else { nt/nc };
                let ddn = ray.direction.dot(n1);
                let cos2t = 1.0 - nnt * nnt * (1.0 - ddn * ddn);
                if cos2t < 0.0 {
                    // Total internal reflection
                    colour = colour * radiance(scene, &reflected_ray, depth, rng);
                } else {
                    let tbd = ddn * nnt + cos2t.sqrt();
                    let tbd = if into { tbd } else { -tbd };
                    let tdir = (ray.direction * nnt - hit_normal * tbd).normalized();
                    let transmitted_ray = Ray::new(hit_pos, tdir);
                    let a = nt - nc;
                    let b = nt + nc;
                    let r0 = (a * a) / (b * b);
                    let c = 1.0 - if into { -ddn } else { tdir.dot(hit_normal) };
                    let re = r0 + (1.0 - r0) * c * c * c * c * c;
                    let tr = 1.0 - re;
                    let p = 0.25 + 0.5 * re;
                    let rp = re / p;
                    let tp = tr / (1.0 - p);
                    colour = colour * if depth > 2 {
                        if rng.gen::<f64>() < p {
                            radiance(scene, &reflected_ray, depth, rng) * rp
                        } else {
                            radiance(scene, &transmitted_ray, depth, rng) * tp
                        }
                    } else {
                        radiance(scene, &reflected_ray, depth, rng) * re +
                            radiance(scene, &transmitted_ray, depth, rng) * tr
                    }
                }
            }
        }
        hit.sphere.emission + colour
    } else {
        Vec3d::zero()
    }
}

fn random_samp<T: Rng>(rng: &mut T) -> f64 {
    let r = 2.0 * rng.gen::<f64>();
    if r < 1.0 { r.sqrt() - 1.0 } else { 1.0 - (2.0 - r).sqrt() }
}

fn to_int(v: f64) -> u8 {
    let ch = (v.powf(1.0/2.2) * 255.0 + 0.5) as i64;
    if ch < 0 { 0 } else if ch > 255 { 255 } else { ch as u8 }
}

fn main() {
    let mut samps = 1;
    let mut width = 1024;
    let mut height = 768;
    let mut output_filename = "image.ppm".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Render a simple image");
        ap.refer(&mut samps).add_option(&["-s", "--samples"], Store, "Number of samples");
        ap.refer(&mut height).add_option(&["-h", "--height"], Store, "Height");
        ap.refer(&mut width).add_option(&["-w", "--width"], Store, "Width");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.parse_args_or_exit();
    }
    samps = samps / 4;
    if samps < 1 { samps = 1; }
    const BLACK : Vec3d = Vec3d { x: 0.0, y: 0.0, z: 0.0 };
    const RED : Vec3d = Vec3d { x: 0.75, y: 0.25, z: 0.25 };
    const BLUE : Vec3d = Vec3d { x: 0.25, y: 0.25, z: 0.75 };
    const GREY : Vec3d = Vec3d { x: 0.75, y: 0.75, z: 0.75 };
    const WHITE : Vec3d = Vec3d { x: 0.999, y: 0.999, z: 0.999 };
    let scene = Arc::new(vec!{
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(1e5+1.0, 40.8, 81.6),
            BLACK, RED),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(-1e5+99.0, 40.8, 81.6),
            BLACK, BLUE),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 40.8, 1e5),
            BLACK, GREY),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 40.8, -1e5 + 170.0),
            BLACK, BLACK),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, 1e5, 81.6),
            BLACK, GREY),
        Sphere::new(Material::Diffuse, 1e5,
            Vec3d::new(50.0, -1e5 + 81.6, 81.6),
            BLACK, GREY),
        Sphere::new(Material::Specular, 16.5,
            Vec3d::new(27.0, 16.5, 47.0),
            BLACK, WHITE),
        Sphere::new(Material::Refractive, 16.5,
            Vec3d::new(73.0, 16.5, 78.0),
            BLACK, WHITE),
        Sphere::new(Material::Diffuse, 600.0,
            Vec3d::new(50.0, 681.6 - 0.27, 81.6),
            Vec3d::new(12.0, 12.0, 12.0), BLACK),
    });

    let camera_pos = Vec3d::new(50.0, 52.0, 295.6);
    let camera_dir = Vec3d::new(0.0, -0.042612, -1.0).normalized();
    let camera_x = Vec3d::new(width as f64 * 0.5135 / height as f64, 0.0, 0.0);
    let camera_y = camera_x.cross(camera_dir).normalized() * 0.5135;

    let num_threads = num_cpus::get();
    println!("Using {} threads", num_threads);
    let pool = ThreadPool::new(num_threads);
    let (tx, rx) = channel();

    for y in 0..height {
        let tx = tx.clone();
        let scene = scene.clone();
        pool.execute(move || {
            let mut line = Vec::with_capacity(width);
            let mut rng = XorShiftRng::from_seed([1 + (y * y) as u32, 0x193a6754, 0x15aac60d, 0xb017f00d]);
            for x in 0..width {
                let mut sum = Vec3d::zero();
                for sx in 0..2 {
                    for sy in 0..2 {
                        for _samp in 0..samps {
                            let dx = random_samp(&mut rng);
                            let dy = random_samp(&mut rng);
                            let sub_x = (sx as f64 + 0.5 + dx) / 2.0;
                            let dir_x = (sub_x + x as f64) / width as f64 - 0.5;
                            let sub_y = (sy as f64 + 0.5 + dy) / 2.0;
                            let dir_y = (sub_y + (height -y - 1) as f64) / height as f64 - 0.5;
                            let dir = (camera_x * dir_x + camera_y * dir_y + camera_dir).normalized();
                            let jittered_ray = Ray::new(camera_pos + dir * 140.0, dir);
                            let sample = radiance(&scene, &jittered_ray, 0, &mut rng);
                            sum = sum + sample;
                        }
                    }
                }
                line.push((sum / (samps * 4) as f64).clamp());
            }
            tx.send((y, line)).unwrap();
        });
    }
    let mut left = height;
    let mut screen : Vec<Vec<Vec3d>> = Vec::new();
    for _y in 0..height {
        screen.push(Vec::new());
    }
    while left > 0 {
        print!("Rendering ({} spp) {:.4}%...\r", samps * 4, 100.0 * (height - left) as f64 / height as f64);
        io::stdout().flush().ok().expect("Could not flush stdout");
        let (y, line) = rx.recv().unwrap();
        screen[y] = line;
        left -= 1;
    }
    println!("\nWriting output to '{}'", output_filename);
    let output_file = File::create(output_filename).unwrap();
    let mut writer = BufWriter::new(output_file);
    write!(&mut writer, "P3\n{} {}\n255\n", width, height).unwrap();
    for y in 0..height {
        for x in 0..width {
            let sum = screen[y][x];
            write!(&mut writer, "{} {} {} ", to_int(sum.x), to_int(sum.y), to_int(sum.z)).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate terminal;
extern crate libc;
extern crate serialize;
extern crate collections;
extern crate getopts;

use getopts::{reqopt,getopts};
use std::os;
use std::io::IoResult;
use std::io::EndOfFile;
use terminal::{Screen,Vte,ScreenError};
use terminal::c_bits::libtsm::*;
use libc::{c_uint,c_void,size_t,uint32_t};
use std::char::from_u32;
use std::str::from_char;
use serialize::{Encodable,Encoder};
use serialize::json;

#[deriving(Show,Copy)]
struct State {
  rendered: Vec<Vec<(String, Attribute)>>
}

#[deriving(Show,Encodable)]
struct CursorState {
  x: u32,
  y: u32,
  visible: bool
}

#[deriving(PartialEq,Show)]
struct Attribute {
  fg: Option<u8>,
  bg: Option<u8>,
  bold: bool,
  underline: bool,
  inverse: bool,
  blink: bool
}

fn main() {
  let args: Vec<String> = os::args();

  let opts = [
      reqopt("h", "height", "the height of the console", "HEIGHT"),
      reqopt("w", "width", "the width of the console", "WIDTH")
  ];
  let matches = match getopts(args.tail(), opts) {
     Ok(m) => { m }
     Err(f) => { fail!("{}", f) }
  };
  let width: u32 = from_str(matches.opt_str("w").unwrap().as_slice()).unwrap();
  let height: u32 = from_str(matches.opt_str("h").unwrap().as_slice()).unwrap();

  let (screen, vte) = match setup_screen(width, height) {
    Err(reason) => { fail!("screen setup failed for {}", reason) }
    Ok(v) => v
  };

  match run(screen, vte) {
    Ok(()) => {},
    Err(reason) => {
      if !(reason.kind == EndOfFile) {
        fail!("runloop failed for {}", reason)
      }
    }
  }
}

fn setup_screen(width: u32, height: u32) -> Result<(Screen,Vte), ScreenError> {
  let screen = try!(Screen::open());
  try!(screen.resize(width,height));
  let vte = try!(screen.vte());
  Ok((screen,vte))
}

fn run(screen: Screen, vte: Vte) -> IoResult<()> {
  let mut stdin = std::io::stdio::stdin();

  loop {
    let line = try!(stdin.read_line());

    match line.as_slice().chars().next() {
      Some('d') => {
        let next_line = try!(stdin.read_line());
        let n: uint = from_str(next_line.as_slice().trim()).expect("d must be followed by int");
        let result = try!(stdin.read_exact(n));
        vte.feed(result.as_slice())
      }
      Some('p') => {
        let mut state = State { rendered: vec![] };
        let state_ptr: *mut c_void = &mut state as *mut _ as *mut c_void;
        screen.draw(draw_cb, state_ptr);
        let encoded = json::encode(&state);
        println!("{}", encoded)
      }
      Some('c') => {
        let (x,y) = screen.cursor_pos();
        let visible = screen.cursor_visible();
        let c_state = CursorState { x: x, y: y, visible: visible };
        let encoded = json::encode(&c_state);
        println!("{}", encoded)
      }
      None => { fail!("empty input!") }
      _ => { fail!("unknown command!") }
    }
  }
}

impl State {
  fn push_if_same(&mut self, ch: char, attr: Attribute) -> bool {
    let current_line  = self.rendered.mut_last().unwrap();
    let current_stream = current_line.mut_last().unwrap();
    if current_stream.ref1() == &attr {
      current_stream.mut0().push_char(ch);
      true
    } else {
      false
    }
  }

  fn push_new_cell(&mut self, ch: char, attr: Attribute) {
    let current_line  = self.rendered.mut_last().unwrap();
    let element = (ch.to_string(), attr);
    current_line.push(element);
  }
}

impl<S: Encoder<E>, E> Encodable<S, E> for State {
  fn encode(&self, s: &mut S) -> Result<(), E> {
    self.rendered.encode(s)
  }
}

impl Attribute {
  fn new(attr: tsm_screen_attr) -> Attribute {
    Attribute {
      fg: attr.get_fg(),
      bg: attr.get_bg(),
      bold: attr.get_flag(Bold),
      underline: attr.get_flag(Underline),
      inverse: attr.get_flag(Inverse),
      blink: attr.get_flag(Blink)
    }
  }
}

impl<S: Encoder<E>, E> Encodable<S, E> for Attribute {
  fn encode(&self, e: &mut S) -> Result<(), E> {
    let fields_to_emit = vec![self.fg.is_some(), self.bg.is_some(), self.bold, self.underline, self.inverse, self.blink];
    let no_of_fields_to_emit = fields_to_emit.iter().filter(|val| **val).count();

    e.emit_map(no_of_fields_to_emit, |e| {
      let mut key_pos = 0;
      if self.fg.is_some() {
        try!(e.emit_map_elt_key(key_pos, |e| "fg".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.fg.encode(e)));
        key_pos = key_pos + 1;
      }
      if self.bg.is_some() {
        try!(e.emit_map_elt_key(key_pos, |e| "bg".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.bg.encode(e)));
        key_pos = key_pos + 1;
      }
      if self.bold {
        try!(e.emit_map_elt_key(key_pos, |e| "bold".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.bold.encode(e)));
        key_pos = key_pos + 1;
      }
      if self.underline {
        try!(e.emit_map_elt_key(key_pos, |e| "underline".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.underline.encode(e)));
        key_pos = key_pos + 1;
      }
      if self.inverse {
        try!(e.emit_map_elt_key(key_pos, |e| "inverse".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.inverse.encode(e)));
        key_pos = key_pos + 1;
      }
      if self.blink {
        try!(e.emit_map_elt_key(key_pos, |e| "blink".encode(e)));
        try!(e.emit_map_elt_val(key_pos, |e| self.blink.encode(e)));
      }

      Ok(())
    })
  }
}

extern "C" fn draw_cb(
  _: *const tsm_screen,
  _: u32,
  ch: *const uint32_t,
  _: size_t,
  _: c_uint,
  _: c_uint,
  posy: c_uint,
  attr: *const tsm_screen_attr,
  _: tsm_age_t,
  data: *mut c_void
) {
  unsafe {
    let data: &mut State = &mut *(data as *mut State);
    let mut current_char;
    let attribute = Attribute::new(*attr);

    if *ch == 0 {
      current_char = ' ';
    } else {
      current_char = from_u32(*ch).unwrap();
    }

    if data.rendered.len() == (posy as uint) {
      data.rendered.push(vec![(from_char(current_char), attribute)]);
      return
    }

    let added = data.push_if_same(current_char, attribute);
    if !added {
      data.push_new_cell(current_char, attribute);
    }
  };
}
<commit_msg>Remove old binary<commit_after><|endoftext|>