<commit_before>use std::io::{Write, BufWriter};
use std::fs::File;
mod vector;
use vector::{Vec3, dot, cross, unit_vector};
mod ray;
use ray::Ray;
mod sphere;
use sphere::{Sphere};
mod hitable;

fn hit_sphere(center: Vec3, radius: f64, ray: Ray) -> f64 {
  let oc = ray.origin() - center;
  let a: f64 = dot(ray.direction(), ray.direction());
  let b: f64 = dot(oc, ray.direction()) * 2.0;
  let c: f64 = dot(oc, oc) - radius * radius;
  let discriminant = b * b - 4.0 * a * c;
  if discriminant < 0.0 {
    return -1.0
  }
  else {
    return (-b - discriminant.sqrt()) / (2.0 * a);
  }
}

fn color(ray : Ray) -> Vec3 {
  let t = hit_sphere(Vec3::new(0.0, 0.0, -1.0), 0.5, ray);
  if t > 0.0 {
    let n = unit_vector(ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0));
    return (Vec3::new(n.x()+1.0, n.y()+1.0, n.z()+1.0)) * 0.5;
  }

  let unit_direction = ray.direction().unit_vector();
  let t = 0.5 * (unit_direction.y() + 1.0);
  return Vec3::new(1.0,1.0,1.0) * (1.0 - t) + Vec3::new(0.5,0.7,1.0) * t;
}

fn main() {
  let nx = 200;
  let ny = 100;
  let data = format!("{}\n{} {}\n{}\n", "P3", nx, ny, 255);
  let f = File::create("target/image.ppm").expect("Unable to create file");
  let mut f = BufWriter::new(f);
  f.write_all(data.as_bytes()).expect("Unable to write data");

  let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
  let horizontal = Vec3::new(4.0, 0.0, 0.0);
  let vertical = Vec3::new(0.0, 2.0, 0.0);
  let origin = Vec3::new(0.0, 0.0, 0.0);

  for j in (0..ny).rev() {
    for i in 0..nx {
      let u = i as f64 / nx as f64;
      let v = j as f64 / ny as f64;
      let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
      let col = color(r);

      let ir = (255.99*col.r()) as i32;
      let ig = (255.99*col.g()) as i32;
      let ib = (255.99*col.b()) as i32;
      f.write_all(format!("{} {} {}\n", ir, ig, ib).as_bytes()).expect("Unable to write data");
    }
  }
}<commit_msg>Group mod statements together<commit_after>use std::io::{Write, BufWriter};
use std::fs::File;

mod vector;
mod ray;
mod sphere;
mod hitable;

use vector::{Vec3, dot, cross, unit_vector};
use ray::Ray;
use sphere::{Sphere};

fn hit_sphere(center: Vec3, radius: f64, ray: Ray) -> f64 {
  let oc = ray.origin() - center;
  let a: f64 = dot(ray.direction(), ray.direction());
  let b: f64 = dot(oc, ray.direction()) * 2.0;
  let c: f64 = dot(oc, oc) - radius * radius;
  let discriminant = b * b - 4.0 * a * c;
  if discriminant < 0.0 {
    return -1.0
  }
  else {
    return (-b - discriminant.sqrt()) / (2.0 * a);
  }
}

fn color(ray : Ray) -> Vec3 {
  let t = hit_sphere(Vec3::new(0.0, 0.0, -1.0), 0.5, ray);
  if t > 0.0 {
    let n = unit_vector(ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0));
    return (Vec3::new(n.x()+1.0, n.y()+1.0, n.z()+1.0)) * 0.5;
  }

  let unit_direction = ray.direction().unit_vector();
  let t = 0.5 * (unit_direction.y() + 1.0);
  return Vec3::new(1.0,1.0,1.0) * (1.0 - t) + Vec3::new(0.5,0.7,1.0) * t;
}

fn main() {
  let nx = 200;
  let ny = 100;
  let data = format!("{}\n{} {}\n{}\n", "P3", nx, ny, 255);
  let f = File::create("target/image.ppm").expect("Unable to create file");
  let mut f = BufWriter::new(f);
  f.write_all(data.as_bytes()).expect("Unable to write data");

  let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
  let horizontal = Vec3::new(4.0, 0.0, 0.0);
  let vertical = Vec3::new(0.0, 2.0, 0.0);
  let origin = Vec3::new(0.0, 0.0, 0.0);

  for j in (0..ny).rev() {
    for i in 0..nx {
      let u = i as f64 / nx as f64;
      let v = j as f64 / ny as f64;
      let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
      let col = color(r);

      let ir = (255.99*col.r()) as i32;
      let ig = (255.99*col.g()) as i32;
      let ib = (255.99*col.b()) as i32;
      f.write_all(format!("{} {} {}\n", ir, ig, ib).as_bytes()).expect("Unable to write data");
    }
  }
}<|endoftext|>


<commit_before>use std::path::Path;

use clap::{App, Arg};

use avsser::generic::input::determine_input_type;
use avsser::generic::input::get_list_of_files;
use avsser::generic::output::create_avs_script;
use avsser::generic::output::extract_fonts;
use avsser::generic::output::AvsOptions;

fn resize_opt_into_dimensions(pair: &str) -> (u32, u32) {
    let items: Vec<&str> = pair.split(|c| c == ',' || c == 'x' || c == 'X').collect();
    if items.len() != 2 {
        panic!("Expected exactly 2 arguments (comma-separated or x-separated) for 'resize'");
    }

    (
        items[0].parse().expect("Invalid width supplied to resizer"),
        items[1]
            .parse()
            .expect("Invalid height supplied to resizer"),
    )
}

fn main() {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::with_name("input").help("the input file to generate a script for").required(true).index(1))
        .arg(Arg::with_name("subtitle")
            .short("s")
            .long("subtitle")
            .help("include subtitles with TextSub(input_filename.ass)"))
        .arg(Arg::with_name("sub-extract").short("S").long("sub-extract").help("extract subtitles from the input files (defaults to track 0)"))
        .arg(Arg::with_name("sub-track").short("T").long("sub-track").help("select which subtitle track to extract, 0-indexed (does nothing without -S)")
            .takes_value(true).value_name("TRACK"))
        .arg(Arg::with_name("audio").short("a").long("audio").help("include audio from video"))
        .arg(Arg::with_name("audio-ext").short("A").long("audio-ext").help("include audio from separate file with specified extension (takes precedence over audio \
         from video)").takes_value(true).value_name("EXT"))
        .arg(Arg::with_name("fonts").short("f").long("fonts").help("extract fonts from mkv container"))
        .arg(Arg::with_name("resize").short("R").long("resize").help("resize video to the given width and height").takes_value(true).value_name("W,H"))
        .arg(Arg::with_name("filters").short("F").long("filters").help("use a custom filter chain instead of RemoveGrain(1)"))
        .arg(Arg::with_name("keep-grain").short("G").long("keep-grain").help("don't add a RemoveGrain(1) filter"))
        .arg(Arg::with_name("120").long("120").help("convert VFR to 120fps CFR (only works with MKVs)"))
        .arg(Arg::with_name("10").long("10").help("decode Hi10p video"))
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let input = get_list_of_files(Path::new(&input), false).unwrap();
    for path in input {
        if determine_input_type(path.as_ref()).is_none() {
            continue;
        }
        if matches.is_present("fonts") {
            extract_fonts(path.as_ref()).unwrap();
        }
        create_avs_script(
            path.as_ref(),
            path.with_extension("avs").as_ref(),
            &AvsOptions {
                filters: if matches.is_present("filters") {
                    matches
                        .value_of("filters")
                        .unwrap()
                        .trim_left_matches('.')
                        .to_string()
                } else if matches.is_present("keep-grain") {
                    String::new()
                } else {
                    "RemoveGrain(1)".to_string()
                },
                ass: matches.is_present("subtitle"),
                ass_extract: if matches.is_present("sub-extract") {
                    Some(
                        matches
                            .value_of("sub-track")
                            .map(|track| {
                                track.parse().expect("Invalid argument supplied for track")
                            })
                            .unwrap_or(0),
                    )
                } else {
                    None
                },
                audio: (
                    matches.is_present("audio"),
                    matches.value_of("audio-ext").map(|ext| ext.to_string()),
                ),
                resize: matches
                    .value_of("resize")
                    .map(|resize| resize_opt_into_dimensions(resize)),
                to_cfr: matches.is_present("120"),
                hi10p: matches.is_present("10"),
            },
        )
        .unwrap();
    }
}
<commit_msg>Refactor script creation in main<commit_after>use std::path::Path;

use clap::App;
use clap::Arg;
use clap::ArgMatches;

use avsser::generic::input::determine_input_type;
use avsser::generic::input::get_list_of_files;
use avsser::generic::output::create_avs_script;
use avsser::generic::output::extract_fonts;
use avsser::generic::output::AvsOptions;

fn main() {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::with_name("input").help("the input file to generate a script for").required(true).index(1))
        .arg(Arg::with_name("subtitle")
            .short("s")
            .long("subtitle")
            .help("include subtitles with TextSub(input_filename.ass)"))
        .arg(Arg::with_name("sub-extract").short("S").long("sub-extract").help("extract subtitles from the input files (defaults to track 0)"))
        .arg(Arg::with_name("sub-track").short("T").long("sub-track").help("select which subtitle track to extract, 0-indexed (does nothing without -S)")
            .takes_value(true).value_name("TRACK"))
        .arg(Arg::with_name("audio").short("a").long("audio").help("include audio from video"))
        .arg(Arg::with_name("audio-ext").short("A").long("audio-ext").help("include audio from separate file with specified extension (takes precedence over audio \
         from video)").takes_value(true).value_name("EXT"))
        .arg(Arg::with_name("fonts").short("f").long("fonts").help("extract fonts from mkv container"))
        .arg(Arg::with_name("resize").short("R").long("resize").help("resize video to the given width and height").takes_value(true).value_name("W,H"))
        .arg(Arg::with_name("filters").short("F").long("filters").help("use a custom filter chain instead of RemoveGrain(1)"))
        .arg(Arg::with_name("keep-grain").short("G").long("keep-grain").help("don't add a RemoveGrain(1) filter"))
        .arg(Arg::with_name("120").long("120").help("convert VFR to 120fps CFR (only works with MKVs)"))
        .arg(Arg::with_name("10").long("10").help("decode Hi10p video"))
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let input = get_list_of_files(Path::new(&input), false).unwrap();
    for path in input {
        if determine_input_type(path.as_ref()).is_none() {
            continue;
        }
        if matches.is_present("fonts") {
            extract_fonts(path.as_ref()).unwrap();
        }
        create_script(&path, &matches).unwrap();
    }
}

fn resize_opt_into_dimensions(pair: &str) -> (u32, u32) {
    let items: Vec<&str> = pair.split(|c| c == ',' || c == 'x' || c == 'X').collect();
    if items.len() != 2 {
        panic!("Expected exactly 2 arguments (comma-separated or x-separated) for 'resize'");
    }

    (
        items[0].parse().expect("Invalid width supplied to resizer"),
        items[1]
            .parse()
            .expect("Invalid height supplied to resizer"),
    )
}

fn create_script(path: &Path, matches: &ArgMatches) -> Result<(), String> {
    create_avs_script(
        path,
        &path.with_extension("avs"),
        &AvsOptions {
            filters: if matches.is_present("filters") {
                matches
                    .value_of("filters")
                    .unwrap()
                    .trim_left_matches('.')
                    .to_string()
            } else if matches.is_present("keep-grain") {
                String::new()
            } else {
                "RemoveGrain(1)".to_string()
            },
            ass: matches.is_present("subtitle"),
            ass_extract: if matches.is_present("sub-extract") {
                Some(
                    matches
                        .value_of("sub-track")
                        .map(|track| track.parse().expect("Invalid argument supplied for track"))
                        .unwrap_or(0),
                )
            } else {
                None
            },
            audio: (
                matches.is_present("audio"),
                matches.value_of("audio-ext").map(|ext| ext.to_string()),
            ),
            resize: matches
                .value_of("resize")
                .map(|resize| resize_opt_into_dimensions(resize)),
            to_cfr: matches.is_present("120"),
            hi10p: matches.is_present("10"),
        },
    )
}
<|endoftext|>


<commit_before>extern crate practice_game;

// Files
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

// Game Objects
use practice_game::unit::{Unit, Hero, NonHero};

// Tests
use std::mem;

const GAME_NAME: &'static str = "Fighter";
const HERO_INIT_HEALTH: f64 = 200.0;
const HERO_INIT_ATTACK: f64 = 20.0;
const NONHERO_INIT_HEALTH: f64 = 100.0;
const NONHERO_INIT_ATTACK: f64 = 10.0;

// ======================================================================
// Abstractions
//
#[derive(Clone)]
pub struct Resources {
    player: Hero,
    enemy: NonHero,
}

impl Resources {
    pub fn realize_player(&self) -> Hero {
        let cloned_self = self.clone();
        cloned_self.player
    }

    pub fn realize_enemy(&self) -> NonHero {
        let cloned_self = self.clone();
        cloned_self.enemy
    }
}
// ======================================================================

// ======================================================================
//
fn main() {
    let database_path = Path::new("database.txt");
    let database_display = database_path.display();
    let mut database_file = match File::open(&database_path) {
        Err(why) => panic!("couldn't open {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(database_file) => database_file, };
    let mut database_reader = String::new();
    match database_file.read_to_string(&mut database_reader) {
        Err(why) => panic!("couldn't read {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(_) => print!("{file} contains:\n{variable}",
                        file = database_display,
                        variable = database_reader), }

    let mut game_data: Resources = Resources {
        player: Hero::new(HERO_INIT_HEALTH, HERO_INIT_ATTACK),
        enemy: NonHero::new(NONHERO_INIT_HEALTH, NONHERO_INIT_ATTACK), };
    println!("Welcome to {}!", GAME_NAME);
    draw_line_break();
    draw_line_break();
    println!("An enemy appears!");
    battle(&mut game_data);
    battle(&mut game_data);

}
// ======================================================================

// ======================================================================
// Helper Routines
//
// UI
//
pub fn draw_line_break() {
    println!("");
}

pub fn draw_hp_bars(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    println!("--------------------");
    println!("enemy: {}", enemy.show());
    println!("player: {}", player.show());
    println!("--------------------");
}

pub fn draw_combat_text(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    let old_health: f64 = enemy.realize_hp() + player.realize_atk();
    let new_health: f64 = enemy.realize_hp();
    let damage: f64 = player.realize_atk();
    print!("{}hp -> ", old_health as i32);
    print!("{}hp ", new_health as i32);
    println!("{}!", damage as i32);
}

// Memory
//
#[allow(dead_code)]
fn show_mem(in_game_data: &Resources) {
    let ref enemy = in_game_data.realize_enemy();
    let ref player = in_game_data.realize_player();

    println!("resource    bytes in the stack");
    println!("GAME_NAME:  {}", mem::size_of_val(&GAME_NAME));
    println!("game_data:  {}", mem::size_of_val(&in_game_data));
    println!("enemy:      {}", mem::size_of_val(&enemy));
    println!("enemy.hp:   {}", mem::size_of_val(&enemy.realize_hp()));
    println!("enemy.atk:  {}", mem::size_of_val(&enemy.realize_atk()));
    println!("player:     {}", mem::size_of_val(&player));
    println!("player.hp:  {}", mem::size_of_val(&player.realize_hp()));
    println!("player.atk: {}", mem::size_of_val(&player.realize_atk()));
    println!("player.lvl: {}", mem::size_of_val(&player.realize_lvl()));
    println!("player.exp: {}", mem::size_of_val(&player.realize_exp()));
}

// Misc
//
fn battle(in_game_data: &mut Resources) {
    let mut game_data: &mut Resources = in_game_data;
    draw_hp_bars(&game_data);
    read_user_input();
    deal_damage(&mut game_data);
    draw_combat_text(&game_data);
    draw_line_break();
    draw_line_break();
}

fn read_user_input() {
    let user_input: &str = &"attack";
    println!("{}", user_input);
}

fn deal_damage(in_game_data: &mut Resources) {
    let cloned_game_data = in_game_data.clone();
    let ref player = cloned_game_data.player;
    let ref mut enemy = in_game_data.enemy;

    let dmg = -player.realize_atk();
    enemy.change_current_hp(dmg);
}
// ======================================================================
<commit_msg>Line 71 & 73: Refactoring: Changed variable to contents.<commit_after>extern crate practice_game;

// Files
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

// Game Objects
use practice_game::unit::{Unit, Hero, NonHero};

// Tests
use std::mem;

const GAME_NAME: &'static str = "Fighter";
const HERO_INIT_HEALTH: f64 = 200.0;
const HERO_INIT_ATTACK: f64 = 20.0;
const NONHERO_INIT_HEALTH: f64 = 100.0;
const NONHERO_INIT_ATTACK: f64 = 10.0;

// ======================================================================
// Abstractions
//
#[derive(Clone)]
pub struct Resources {
    player: Hero,
    enemy: NonHero,
}

impl Resources {
    pub fn realize_player(&self) -> Hero {
        let cloned_self = self.clone();
        cloned_self.player
    }

    pub fn realize_enemy(&self) -> NonHero {
        let cloned_self = self.clone();
        cloned_self.enemy
    }
}
// ======================================================================

// ======================================================================
//
fn main() {
    let database_path = Path::new("database.txt");
    let database_display = database_path.display();
    let mut database_file = match File::open(&database_path) {
        Err(why) => panic!("couldn't open {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(database_file) => database_file, };
    let mut database_reader = String::new();
    match database_file.read_to_string(&mut database_reader) {
        Err(why) => panic!("couldn't read {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(_) => print!("{file} contains:\n{contents}",
                        file = database_display,
                        contents = database_reader), }

    let mut game_data: Resources = Resources {
        player: Hero::new(HERO_INIT_HEALTH, HERO_INIT_ATTACK),
        enemy: NonHero::new(NONHERO_INIT_HEALTH, NONHERO_INIT_ATTACK), };
    println!("Welcome to {}!", GAME_NAME);
    draw_line_break();
    draw_line_break();
    println!("An enemy appears!");
    battle(&mut game_data);
    battle(&mut game_data);

}
// ======================================================================

// ======================================================================
// Helper Routines
//
// UI
//
pub fn draw_line_break() {
    println!("");
}

pub fn draw_hp_bars(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    println!("--------------------");
    println!("enemy: {}", enemy.show());
    println!("player: {}", player.show());
    println!("--------------------");
}

pub fn draw_combat_text(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    let old_health: f64 = enemy.realize_hp() + player.realize_atk();
    let new_health: f64 = enemy.realize_hp();
    let damage: f64 = player.realize_atk();
    print!("{}hp -> ", old_health as i32);
    print!("{}hp ", new_health as i32);
    println!("{}!", damage as i32);
}

// Memory
//
#[allow(dead_code)]
fn show_mem(in_game_data: &Resources) {
    let ref enemy = in_game_data.realize_enemy();
    let ref player = in_game_data.realize_player();

    println!("resource    bytes in the stack");
    println!("GAME_NAME:  {}", mem::size_of_val(&GAME_NAME));
    println!("game_data:  {}", mem::size_of_val(&in_game_data));
    println!("enemy:      {}", mem::size_of_val(&enemy));
    println!("enemy.hp:   {}", mem::size_of_val(&enemy.realize_hp()));
    println!("enemy.atk:  {}", mem::size_of_val(&enemy.realize_atk()));
    println!("player:     {}", mem::size_of_val(&player));
    println!("player.hp:  {}", mem::size_of_val(&player.realize_hp()));
    println!("player.atk: {}", mem::size_of_val(&player.realize_atk()));
    println!("player.lvl: {}", mem::size_of_val(&player.realize_lvl()));
    println!("player.exp: {}", mem::size_of_val(&player.realize_exp()));
}

// Misc
//
fn battle(in_game_data: &mut Resources) {
    let mut game_data: &mut Resources = in_game_data;
    draw_hp_bars(&game_data);
    read_user_input();
    deal_damage(&mut game_data);
    draw_combat_text(&game_data);
    draw_line_break();
    draw_line_break();
}

fn read_user_input() {
    let user_input: &str = &"attack";
    println!("{}", user_input);
}

fn deal_damage(in_game_data: &mut Resources) {
    let cloned_game_data = in_game_data.clone();
    let ref player = cloned_game_data.player;
    let ref mut enemy = in_game_data.enemy;

    let dmg = -player.realize_atk();
    enemy.change_current_hp(dmg);
}
// ======================================================================
<|endoftext|>


<commit_before>#![allow(dead_code)]
#[derive(PartialEq,Debug)]
enum Data {
    Nil,
    Symbol(String),
    Atom(f32),
    Cons ( Box<Data>, Box<Data> )
}

fn cons (car:Data, cdr:Data) -> Data {
    Data::Cons( Box::new(car), Box::new(cdr) )
}

fn nreverse (list: Data) -> Data{
    let mut curr = list;
    let mut prv = Box::new(Data::Nil);

    while curr != Data::Nil {
        match curr {
            Data::Nil => unreachable!(),
            Data:: Symbol(_) |Data::Atom(_) => {panic!("Not a proper list!")},
            Data::Cons(_, ref mut next) =>{
               std::mem::swap(next, &mut prv);
            }
        };
        std::mem::swap(&mut curr, &mut prv);

    }
    *prv
}

fn car (d:Data) -> Data {
    match d {
        Data::Nil => Data::Nil,
        Data::Cons(a, _) => *a,
        v@Data::Symbol(_) | v@Data::Atom(_) => v,
    }
}

fn cdr (d:Data) -> Data {
    match d {
        Data::Nil => Data::Nil,
        Data::Cons(_, b) => *b,
        v@Data::Symbol(_) | v@Data::Atom(_) => v,
    }
}

fn cadr (d:Data) -> Data {
    car(cdr(d))
}

macro_rules! list {
    ( $( $item:expr),* ) => {
        {
            let mut list:Data = Data::Nil;
            $(
                // TODO: Make consable a trait, and get this working.
                list = cons(Data::Atom($item), list);
                )*
                list
        }
    };
}

fn print_list(list:&Data) {
    print!("(");
    print_listh(list);
}

fn print_listh(list:&Data) {

    match *list {
        Data::Nil => {print!(")");},
        Data::Atom(ref s) => print!("{} ", *s),
        Data::Symbol(ref s) => print!("{} ", s),
        Data::Cons(ref a, ref b) => {
            match **a {
                Data::Nil => { print!("()"); }
                Data::Cons(_,_) => { print!("("); }
                _ => {;}
            }
            print_listh(a);
            print_listh(b);
        },
    }
}

fn tokenize(chars:&str) -> Vec<String>{
    /* Takes a string of chars and returns a vector of tokens. */

    chars.replace("(", " ( ")
        .replace(")", " ) ")
        .split(' ')
        .filter(|s| !(s.is_empty()))
        .map(|s| s.to_string())
        .collect()
}

fn read_from_tokens(tokens:&mut std::iter::Peekable<std::slice::Iter<String>>) -> Data {
    /* Reads an expression from a sequence of tokens. " */

    if tokens.len() == 0 {
        panic!("Unexpected EOF while parsing.");
    }

    let token = tokens.next().unwrap();

    if token == "(" {
        let mut l = Data::Nil;
        while *tokens.peek().unwrap() != ")" {
            l = cons(read_from_tokens(tokens), l);
        }
        tokens.next();
        return nreverse(l);
    }

    return Data::Symbol(token.to_string())
}

fn parse(program:&str) -> Data {
    return read_from_tokens(&mut tokenize(program).iter().peekable());
}

fn main() {
    let parsed = parse("(begin (define r 10) (* pi (* r r)))");
    print_list(&parsed);
}
<commit_msg>Added pretty-printing support and dotted pair support.<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_mut)]

use std::slice::Iter;
use std::iter::Peekable;
use std::collections::HashMap;

#[derive(PartialEq,Debug)]
enum Data {
    Nil,
    Symbol(String),
    Atom(f32),
    Cons ( Box<Data>, Box<Data> )
}

fn cons (car:Data, cdr:Data) -> Data {
    Data::Cons( Box::new(car), Box::new(cdr) )
}

fn nreverse (list: Data) -> Data{
    let mut curr = list;
    let mut prv = Box::new(Data::Nil);

    while curr != Data::Nil {
        match curr {
            Data::Nil => unreachable!(),
            Data:: Symbol(_) |Data::Atom(_) => {panic!("Not a proper list!")},
            Data::Cons(_, ref mut next) =>{
               std::mem::swap(next, &mut prv);
            }
        };
        std::mem::swap(&mut curr, &mut prv);

    }
    *prv
}

fn car (d:Data) -> Data {
    match d {
        Data::Nil => Data::Nil,
        Data::Cons(a, _) => *a,
        v@Data::Symbol(_) | v@Data::Atom(_) => v,
    }
}

fn cdr (d:Data) -> Data {
    match d {
        Data::Nil => Data::Nil,
        Data::Cons(_, b) => *b,
        v@Data::Symbol(_) | v@Data::Atom(_) => v,
    }
}

fn cadr (d:Data) -> Data {
    car(cdr(d))
}

macro_rules! list {
    ( $( $item:expr),* ) => {
        {
            let mut list:Data = Data::Nil;
            $(
                // TODO: Make consable a trait, and get this working.
                list = cons(Data::Atom($item), list);
                )*
                list
        }
    };
}

fn print(list:&Data) {
    printh(list);
    print!("\n");
}

fn printh(list:&Data) {
    match *list {
        Data::Atom(ref s) => print!("{}", *s),
        Data::Symbol(ref s) => print!("{}", *s),
        Data::Nil => print!("Nil"),
        Data::Cons(ref a, ref b) => {
            print!("(");
            printh(a);
            let mut c = b;
            while **c != Data::Nil {
                match **c {
                    Data::Nil => {unreachable!();},
                    Data::Cons(ref a, ref b) => {
                        print!(" ");
                        printh(a);
                        c = b;
                    }
                    _ => { print!(" . ");
                           printh(&*c);
                           print!(")");
                           return;
                    }
                }
            }
            print!(")");
        }
    };
}

fn tokenize(chars:&str) -> Vec<String>{
    /* Takes a string of chars and returns a vector of tokens. */

    chars.replace("(", " ( ")
        .replace(")", " ) ")
        .split(' ')
        .filter(|s| !(s.is_empty()))
        .map(|s| s.to_string())
        .collect()
}

fn read_from_tokens(tokens:&mut Peekable<Iter<String>>) -> Data {
    /* Reads an expression from a sequence of tokens. " */

    if tokens.len() == 0 {
        panic!("Unexpected EOF while parsing.");
    }

    let token = tokens.next().unwrap();

    if token == "(" {
        let mut l = Data::Nil;
        while *tokens.peek().unwrap() != ")" {
            l = cons(read_from_tokens(tokens), l);
        }
        tokens.next();
        return nreverse(l);
    }

    return Data::Symbol(token.to_string())
}

fn parse(program:&str) -> Data {
    return read_from_tokens(&mut tokenize(program).iter().peekable());
}

fn eval(val:Data, env:HashMap<String,f32>) -> f32 {
    match val {
        Data::Symbol(ref s) => *env.get(s).unwrap(),
        Data::Atom(f) => f,
        Data::Nil => unreachable!(),
        Data::Cons(a, b) => apply(*a, *b),
    }
}

fn apply(fun:Data, arguments:Data) -> f32 {
    return 0.0;
}

fn main() {
    let mut env:HashMap<&str,Data> = HashMap::new();
    let parsed = parse("(begin (define r 10) (* pi (* r r)))");
    print(&parsed);
    print(&cons(Data::Symbol("Love".to_string()), Data::Symbol("You".to_string())));
}
<|endoftext|>


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

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

// // // // // // // // // // CONSTANTS // // // // // // // // // //

const SERVICE_ID: u16 = 1;

const TX_CREATE_WALLET_ID: u16 = 1;

const TX_TRANSFER_ID: u16 = 2;

const INIT_BALANCE: u64 = 100;

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

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Api for CryptocurrencyApi {
    fn wire(&self, router: &mut Router) {

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

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

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

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

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

struct CurrencyService;

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

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

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

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

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

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

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

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

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

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

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

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

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

    println!("Blockchain in ready for transactions!");
    node.run().unwrap();
}
<commit_msg>Use Option::is_none instead of pattern matching<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

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

// // // // // // // // // // CONSTANTS // // // // // // // // // //

const SERVICE_ID: u16 = 1;

const TX_CREATE_WALLET_ID: u16 = 1;

const TX_TRANSFER_ID: u16 = 2;

const INIT_BALANCE: u64 = 100;

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

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Api for CryptocurrencyApi {
    fn wire(&self, router: &mut Router) {

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

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

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

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

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

struct CurrencyService;

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

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

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

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

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

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

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

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

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

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

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

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

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

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


<commit_before>#![cfg_attr(test, allow(dead_code))]
#![feature(collections, scoped, convert)]

extern crate unicode_width;

mod args;
mod matching;
mod screen;
mod version;
#[cfg(not(windows))] mod ansi;

use version::*;
use std::process;
use std::io::{stdin, BufRead};
use std::cmp::min;
use screen::Screen;
use screen::Key;
use screen::Key::*;
use self::SearchState::*;
use unicode_width::UnicodeWidthStr;

fn main() {
    let args = match args::parse_args() {
        Some(args) => args,
        None => {
            process::exit(1);
        },
    };

    if args.help { return; }

    if args.version {
        println!("heatseeker {} ({}) (built {})", VERSION, COMMIT, TIMESTAMP);
        return;
    }

    let choices = read_choices();
    let initial_search = args.initial_search.clone();
    let choices = choices.iter().map(|x| &x[..]).collect::<Vec<&str>>();
    if args.use_first {
        let matches = matching::compute_matches(&choices, &initial_search);
        println!("{}", matches.get(0).unwrap_or(&""));
        return;
    } else {
        event_loop(&choices, &initial_search);
    }
}

fn event_loop(choices: &[&str], initial_search: &str) {
    let mut search = Search::new(choices, initial_search.to_string());
    let mut screen = Screen::open_screen();

    loop {
        search.recompute_matches();

        match search.state {
            InProgress => draw_screen(&mut screen, &search),
            _ => break,
        }

        let keys = screen.get_buffered_keys();
        for key in keys.iter() {
            handle_key(&mut search, key, screen.visible_choices);
        }
    }

    screen.move_cursor_to_bottom();
    println!("{}", search.get_selection());
}

fn handle_key(search: &mut Search, key: &Key, visible_choices: u16) {
    match *key {
        Char(x) => search.append(x),
        Backspace => search.backspace(),
        Control('h') => search.backspace(),
        Control('w') => search.delete_word(),
        Control('u') => search.clear_query(),
        Control('c') => search.cancel(),
        Control('g') => search.cancel(),
        Control('p') => search.up(visible_choices),
        Control('n') => search.down(visible_choices),
        Tab => search.down(visible_choices),
        Enter => search.done(),
        _ => {}
    }
}

struct Search<'a> {
    choices: &'a [&'a str],
    query: String,
    matches: Vec<&'a str>,
    stale: bool,
    index: usize,
    state: SearchState,
}

#[derive(PartialEq, Eq)]
enum SearchState {
    InProgress,
    Done,
    Canceled,
}

impl<'a> Search<'a> {
    fn new(choices: &'a [&'a str], initial_search: String) -> Search<'a> {
        let matches = choices.to_vec();
        Search {
            choices: choices,
            query: initial_search,
            matches: matches,
            stale: true,
            index: 0,
            state: InProgress,
        }
    }

    fn up(&mut self, visible_choices: u16) {
        let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
        self.index = if self.index == 0 { limit } else { self.index - 1 };
    }

    fn down(&mut self, visible_choices: u16) {
        let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
        self.index = if self.index == limit { 0 } else { self.index + 1 }
    }

    fn backspace(&mut self) {
        self.query.pop();
        self.stale = true;
        self.index = 0;
        self.matches = self.choices.to_vec();
    }

    fn delete_word(&mut self) {
        self.stale = true;
        delete_last_word(&mut self.query);
        self.matches = self.choices.to_vec();
    }

    fn append(&mut self, c: char) {
        self.query.push(c);
        self.stale = true;
        self.index = 0;
    }

    fn clear_query(&mut self) {
        self.query.clear();
        self.matches = self.choices.to_vec();
    }

    fn recompute_matches(&mut self) {
        if self.stale {
            self.matches = matching::compute_matches(&self.matches, &self.query);
            self.stale = false;
        }
    }

    fn get_selection(&mut self) -> String {
        if self.state == Canceled {
            "".to_string()
        } else {
            self.recompute_matches();
            self.matches.get(self.index).unwrap_or(&"").to_string()
        }
    }

    fn cancel(&mut self) {
        self.state = Canceled
    }

    fn done(&mut self) {
        self.state = Done
    }
}

fn draw_screen(screen: &mut Screen, search: &Search) {
    screen.hide_cursor();
    screen.blank_screen();
    screen.write(&format!("> {} ({}/{} choices)\n", search.query, search.matches.len(), search.choices.len()));

    print_matches(screen, &search.matches, &search.query, search.index);

    let start = screen.start_line;
    screen.move_cursor(start, 2 + UnicodeWidthStr::width(search.query.as_str()) as u16);
    screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &[&str], query: &str, index: usize) {
    let mut i = 1;
    for choice in matches.iter() {
        let indices = matching::visual_score(choice, query);
        let max_width = screen.width;
        print_match(choice, &indices, max_width, &mut |s, highlight| {
            if i == index + 1 {
                if highlight { screen.write_red_inverted(s); } else { screen.write_inverted(s); }
            } else {
                if highlight { screen.write_red(s); } else { screen.write(s); }
            }
        });
        if i >= screen.visible_choices as usize {
            return;
        } else {
            screen.write("\n");
        }
        i += 1;
    }
}

fn print_match(choice: &str, indices: &[usize], max_width: u16, writer: &mut FnMut(&str, bool)) {
    #[cfg(windows)] const MARGIN: u16 = 1;
    #[cfg(not(windows))] const MARGIN: u16 = 0;
    let max_width = max_width - MARGIN;
    let chars_in_choice = choice.chars().count();
    let chars_to_draw = min(chars_in_choice, max_width as usize);
    let mut last_idx = 0;
    for &idx in indices {
        let idx = min(idx, chars_to_draw);
        if last_idx >= chars_to_draw {
            return;
        }
        writer(&choice.slice_chars(last_idx, idx), false);
        if idx == chars_to_draw { return }
        writer(&choice.slice_chars(idx, idx + 1), true);
        last_idx = idx + 1;
    }
    writer(&choice.slice_chars(last_idx, chars_to_draw), false);
}

fn read_choices() -> Vec<String> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let mut stdin = stdin.lock();
    loop {
        let mut s = String::new();
        stdin.read_line(&mut s).unwrap();
        if s.len() == 0 {
            break;
        } else {
            trim(&mut s);
            lines.push(s);
        }
    }

    lines
}

pub fn trim(s: &mut String) {
    while let Some(x) = s.pop() {
        if x != '\n' {
            s.push(x);
            return;
        }
    }
}

fn delete_last_word(s: &mut String) {
    let mut deleted_something = false;
    while let Some(x) = s.pop() {
        if x == ' ' {
            if deleted_something {
                s.push(x);
                return;
            }
        } else {
            deleted_something = true;
        }
    }
}

#[test]
fn trim_test() {
    fn should_become(before: &str, after: &str) {
        let mut x = before.to_string();
        trim(&mut x);
        assert_eq!(after.to_string(), x);
    }
    should_become("", "");
    should_become("\n", "");
    should_become("\n\n", "");
    should_become("asdf", "asdf");
    should_become("asdf\n", "asdf");
    should_become("asdf\nasdf\n", "asdf\nasdf");
}

#[test]
fn delete_word_test() {
    fn should_become(before: &str, after: &str) {
        let mut x = before.to_string();
        delete_last_word(&mut x);
        assert_eq!(after.to_string(), x);
    }
    should_become("", "");
    should_become("a", "");
    should_become("asdf", "");
    should_become("asdf asdf asdf", "asdf asdf ");
    should_become("asdf asdf asdf ", "asdf asdf ");
    should_become("asdf asdf asdf  ", "asdf asdf ");
}
<commit_msg>Remove convert feature<commit_after>#![cfg_attr(test, allow(dead_code))]
#![feature(collections, scoped)]

extern crate unicode_width;

mod args;
mod matching;
mod screen;
mod version;
#[cfg(not(windows))] mod ansi;

use version::*;
use std::process;
use std::io::{stdin, BufRead};
use std::cmp::min;
use screen::Screen;
use screen::Key;
use screen::Key::*;
use self::SearchState::*;
use unicode_width::UnicodeWidthStr;

fn main() {
    let args = match args::parse_args() {
        Some(args) => args,
        None => {
            process::exit(1);
        },
    };

    if args.help { return; }

    if args.version {
        println!("heatseeker {} ({}) (built {})", VERSION, COMMIT, TIMESTAMP);
        return;
    }

    let choices = read_choices();
    let initial_search = args.initial_search.clone();
    let choices = choices.iter().map(|x| &x[..]).collect::<Vec<&str>>();
    if args.use_first {
        let matches = matching::compute_matches(&choices, &initial_search);
        println!("{}", matches.get(0).unwrap_or(&""));
        return;
    } else {
        event_loop(&choices, &initial_search);
    }
}

fn event_loop(choices: &[&str], initial_search: &str) {
    let mut search = Search::new(choices, initial_search.to_string());
    let mut screen = Screen::open_screen();

    loop {
        search.recompute_matches();

        match search.state {
            InProgress => draw_screen(&mut screen, &search),
            _ => break,
        }

        let keys = screen.get_buffered_keys();
        for key in keys.iter() {
            handle_key(&mut search, key, screen.visible_choices);
        }
    }

    screen.move_cursor_to_bottom();
    println!("{}", search.get_selection());
}

fn handle_key(search: &mut Search, key: &Key, visible_choices: u16) {
    match *key {
        Char(x) => search.append(x),
        Backspace => search.backspace(),
        Control('h') => search.backspace(),
        Control('w') => search.delete_word(),
        Control('u') => search.clear_query(),
        Control('c') => search.cancel(),
        Control('g') => search.cancel(),
        Control('p') => search.up(visible_choices),
        Control('n') => search.down(visible_choices),
        Tab => search.down(visible_choices),
        Enter => search.done(),
        _ => {}
    }
}

struct Search<'a> {
    choices: &'a [&'a str],
    query: String,
    matches: Vec<&'a str>,
    stale: bool,
    index: usize,
    state: SearchState,
}

#[derive(PartialEq, Eq)]
enum SearchState {
    InProgress,
    Done,
    Canceled,
}

impl<'a> Search<'a> {
    fn new(choices: &'a [&'a str], initial_search: String) -> Search<'a> {
        let matches = choices.to_vec();
        Search {
            choices: choices,
            query: initial_search,
            matches: matches,
            stale: true,
            index: 0,
            state: InProgress,
        }
    }

    fn up(&mut self, visible_choices: u16) {
        let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
        self.index = if self.index == 0 { limit } else { self.index - 1 };
    }

    fn down(&mut self, visible_choices: u16) {
        let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
        self.index = if self.index == limit { 0 } else { self.index + 1 }
    }

    fn backspace(&mut self) {
        self.query.pop();
        self.stale = true;
        self.index = 0;
        self.matches = self.choices.to_vec();
    }

    fn delete_word(&mut self) {
        self.stale = true;
        delete_last_word(&mut self.query);
        self.matches = self.choices.to_vec();
    }

    fn append(&mut self, c: char) {
        self.query.push(c);
        self.stale = true;
        self.index = 0;
    }

    fn clear_query(&mut self) {
        self.query.clear();
        self.matches = self.choices.to_vec();
    }

    fn recompute_matches(&mut self) {
        if self.stale {
            self.matches = matching::compute_matches(&self.matches, &self.query);
            self.stale = false;
        }
    }

    fn get_selection(&mut self) -> String {
        if self.state == Canceled {
            "".to_string()
        } else {
            self.recompute_matches();
            self.matches.get(self.index).unwrap_or(&"").to_string()
        }
    }

    fn cancel(&mut self) {
        self.state = Canceled
    }

    fn done(&mut self) {
        self.state = Done
    }
}

fn draw_screen(screen: &mut Screen, search: &Search) {
    screen.hide_cursor();
    screen.blank_screen();
    screen.write(&format!("> {} ({}/{} choices)\n", search.query, search.matches.len(), search.choices.len()));

    print_matches(screen, &search.matches, &search.query, search.index);

    let start = screen.start_line;
    let query_str: &str = &search.query;
    screen.move_cursor(start, 2 + UnicodeWidthStr::width(query_str) as u16);
    screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &[&str], query: &str, index: usize) {
    let mut i = 1;
    for choice in matches.iter() {
        let indices = matching::visual_score(choice, query);
        let max_width = screen.width;
        print_match(choice, &indices, max_width, &mut |s, highlight| {
            if i == index + 1 {
                if highlight { screen.write_red_inverted(s); } else { screen.write_inverted(s); }
            } else {
                if highlight { screen.write_red(s); } else { screen.write(s); }
            }
        });
        if i >= screen.visible_choices as usize {
            return;
        } else {
            screen.write("\n");
        }
        i += 1;
    }
}

fn print_match(choice: &str, indices: &[usize], max_width: u16, writer: &mut FnMut(&str, bool)) {
    #[cfg(windows)] const MARGIN: u16 = 1;
    #[cfg(not(windows))] const MARGIN: u16 = 0;
    let max_width = max_width - MARGIN;
    let chars_in_choice = choice.chars().count();
    let chars_to_draw = min(chars_in_choice, max_width as usize);
    let mut last_idx = 0;
    for &idx in indices {
        let idx = min(idx, chars_to_draw);
        if last_idx >= chars_to_draw {
            return;
        }
        writer(&choice.slice_chars(last_idx, idx), false);
        if idx == chars_to_draw { return }
        writer(&choice.slice_chars(idx, idx + 1), true);
        last_idx = idx + 1;
    }
    writer(&choice.slice_chars(last_idx, chars_to_draw), false);
}

fn read_choices() -> Vec<String> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let mut stdin = stdin.lock();
    loop {
        let mut s = String::new();
        stdin.read_line(&mut s).unwrap();
        if s.len() == 0 {
            break;
        } else {
            trim(&mut s);
            lines.push(s);
        }
    }

    lines
}

pub fn trim(s: &mut String) {
    while let Some(x) = s.pop() {
        if x != '\n' {
            s.push(x);
            return;
        }
    }
}

fn delete_last_word(s: &mut String) {
    let mut deleted_something = false;
    while let Some(x) = s.pop() {
        if x == ' ' {
            if deleted_something {
                s.push(x);
                return;
            }
        } else {
            deleted_something = true;
        }
    }
}

#[test]
fn trim_test() {
    fn should_become(before: &str, after: &str) {
        let mut x = before.to_string();
        trim(&mut x);
        assert_eq!(after.to_string(), x);
    }
    should_become("", "");
    should_become("\n", "");
    should_become("\n\n", "");
    should_become("asdf", "asdf");
    should_become("asdf\n", "asdf");
    should_become("asdf\nasdf\n", "asdf\nasdf");
}

#[test]
fn delete_word_test() {
    fn should_become(before: &str, after: &str) {
        let mut x = before.to_string();
        delete_last_word(&mut x);
        assert_eq!(after.to_string(), x);
    }
    should_become("", "");
    should_become("a", "");
    should_become("asdf", "");
    should_become("asdf asdf asdf", "asdf asdf ");
    should_become("asdf asdf asdf ", "asdf asdf ");
    should_become("asdf asdf asdf  ", "asdf asdf ");
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![feature(env)]
#![feature(fs)]
#![feature(path)]
#![feature(process)]
#![feature(tempdir)]

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

use std::env;
use std::fs::{PathExt, TempDir, self};
use std::path::Path;
use std::process::{Command, Stdio};

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

    let args: Vec<_> = env::args().skip(1).collect();

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

        // Inherit stdio
        cmd.stderr(Stdio::inherit());
        cmd.stdin(Stdio::inherit());
        cmd.stdout(Stdio::inherit());

        info!("cwd: . | cmd: `{:?}`", cmd);
        match cmd.output() {
            Err(e) => panic!("`{:?}` failed: {}", cmd, e),
            Ok(output) =>  {
                env::set_exit_status(output.status.code().unwrap());

                return;
            },
        }
    }

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

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

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = env::current_dir().ok().expect("Couldn't fetch the current directory");
    for arg in compiler_args.iter().filter(|arg| **arg != "--run") {
        let path = Path::new(arg);

        if path.exists() && path.is_relative() {
            cmd.arg(&current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }

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

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Compile
    info!("cwd: {} | cmd: `{:?}`", temp_dir_display, cmd);
    match cmd.current_dir(temp_dir_path).output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {
            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }

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

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Execute
    info!("cwd: . | cmd: `{:?}`", cmd);
    match cmd.output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {

            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }
}
<commit_msg>fix: update to rust nightly<commit_after>#![deny(warnings)]
#![feature(exit_status)]
#![feature(fs)]
#![feature(path)]
#![feature(process)]
#![feature(tempdir)]

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

use std::env;
use std::fs::{PathExt, TempDir, self};
use std::path::Path;
use std::process::{Command, Stdio};

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

    let args: Vec<_> = env::args().skip(1).collect();

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

        // Inherit stdio
        cmd.stderr(Stdio::inherit());
        cmd.stdin(Stdio::inherit());
        cmd.stdout(Stdio::inherit());

        info!("cwd: . | cmd: `{:?}`", cmd);
        match cmd.output() {
            Err(e) => panic!("`{:?}` failed: {}", cmd, e),
            Ok(output) =>  {
                env::set_exit_status(output.status.code().unwrap());

                return;
            },
        }
    }

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

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

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = env::current_dir().ok().expect("Couldn't fetch the current directory");
    for arg in compiler_args.iter().filter(|arg| **arg != "--run") {
        let path = Path::new(arg);

        if path.exists() && path.is_relative() {
            cmd.arg(&current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }

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

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Compile
    info!("cwd: {} | cmd: `{:?}`", temp_dir_display, cmd);
    match cmd.current_dir(temp_dir_path).output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {
            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }

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

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Execute
    info!("cwd: . | cmd: `{:?}`", cmd);
    match cmd.output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {

            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate serde_json;

#[macro_use]
extern crate error_type;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate clap;

use std::fs::File;
use std::io::Read;
use std::io::{Write, stderr};
use std::process::exit;
use std::path::{Path, PathBuf};
use serde_json::Value;
use ct_result::{CtResult, CtError};
use config::Config;
use cmd::Cmd;

mod ct_result;
mod dirs;
mod config;
mod cmd;

fn main() {
    execute().unwrap_or_else(|err| {
        let _ = writeln!(&mut stderr(), "{}", err);
        exit(1);
    });
}

fn execute() -> CtResult<()> {
    let config = try!(Config::from_command_args());
    let cmd = try!(get_cmd(&config.cpp_file, &config.db_files));
    try!(cmd.exec());
    Ok(())
}

fn get_cmd(cpp_file: &Path, db_files: &[PathBuf]) -> CtResult<Cmd> {
    if let Some(cmd) = try!(Cmd::from_cache(cpp_file)) {
        return Ok(cmd);
    }

    let mut file_buffer = String::new();

    for db_file in db_files {
        let mut file = try!(File::open(db_file));
        file_buffer.clear();
        try!(file.read_to_string(&mut file_buffer));

        let json_value: Value = try!(serde_json::from_str(&file_buffer));

        let objs = try!(json_value.as_array()
            .ok_or(CtError::from(format!("Expected a json array but got: '{}'", json_value))));

        for obj in objs {
            let obj = try!(obj.as_object()
                .ok_or(CtError::from(format!("Expected a json object but got: '{}'", obj))));

            let cmd = try!(Cmd::from_json_obj(obj));
            if cmd.has_cpp_file(cpp_file) {
                try!(cmd.write_to_cache());
                return Ok(cmd);
            }
        }
    }

    Err(CtError::from(format!("Couldn't find C++ source file '{:?}' in compilation databases '{:?}'!", cpp_file, db_files)))
}
<commit_msg>Give Config struct to get_cmd function<commit_after>#![allow(dead_code)]

extern crate serde_json;

#[macro_use]
extern crate error_type;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate clap;

use std::fs::File;
use std::io::Read;
use std::io::{Write, stderr};
use std::process::exit;
use serde_json::Value;
use ct_result::{CtResult, CtError};
use config::Config;
use cmd::Cmd;

mod ct_result;
mod dirs;
mod config;
mod cmd;

fn main() {
    execute().unwrap_or_else(|err| {
        let _ = writeln!(&mut stderr(), "{}", err);
        exit(1);
    });
}

fn execute() -> CtResult<()> {
    let config = try!(Config::from_command_args());
    let cmd = try!(get_cmd(&config));
    try!(cmd.exec());
    Ok(())
}

fn get_cmd(config: &Config) -> CtResult<Cmd> {
    if let Some(cmd) = try!(Cmd::from_cache(&config.cpp_file)) {
        return Ok(cmd);
    }

    let mut file_buffer = String::new();

    for db_file in &config.db_files {
        let mut file = try!(File::open(db_file));
        file_buffer.clear();
        try!(file.read_to_string(&mut file_buffer));

        let json_value: Value = try!(serde_json::from_str(&file_buffer));

        let objs = try!(json_value.as_array()
            .ok_or(CtError::from(format!("Expected a json array but got: '{}'", json_value))));

        for obj in objs {
            let obj = try!(obj.as_object()
                .ok_or(CtError::from(format!("Expected a json object but got: '{}'", obj))));

            let cmd = try!(Cmd::from_json_obj(obj));
            if cmd.has_cpp_file(&config.cpp_file) {
                try!(cmd.write_to_cache());
                return Ok(cmd);
            }
        }
    }

    Err(CtError::from(format!("Couldn't find C++ source file '{:?}' in compilation databases '{:?}'!",
                              &config.cpp_file,
                              &config.db_files)))
}
<|endoftext|>


<commit_before>// TODO
// impl ToGeojson for ....
// generic number instead of f64 for position?

extern crate serialize;

use std::collections::TreeMap;
use serialize::json::ToJson;
use serialize::json;

/// Pos (alias for Positions)
///
/// [GeoJSON Format Specification § 2.1.1](http://geojson.org/geojson-spec.html#positions)
pub struct Pos(pub Vec<f64>);

impl ToJson for Pos {
    fn to_json(&self) -> json::Json {
        let &Pos(ref nums) = self;
        nums.to_json()
    }
}

impl Clone for Pos {
    fn clone(&self) -> Pos {
        let &Pos(ref nums) = self;
        Pos(nums.clone())
    }
}

/// Point
///
/// [GeoJSON Format Specification § 2.1.2](http://geojson.org/geojson-spec.html#point)
pub struct Point {
    pub coordinates: Pos,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiPoint
///
/// [GeoJSON Format Specification § 2.1.3](http://geojson.org/geojson-spec.html#multipoint)
pub struct MultiPoint {
    pub points: Vec<Point>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Pos> =
            self.points.iter().map(|p| p.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// LineString
///
/// [GeoJSON Format Specification § 2.1.4](http://geojson.org/geojson-spec.html#linestring)
pub struct LineString {
    pub coordinates: Vec<Pos>,
}

impl ToJson for LineString {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "LineString".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiLineString
///
/// [GeoJSON Format Specification § 2.1.5](http://geojson.org/geojson-spec.html#multilinestring)
pub struct MultiLineString {
    pub line_strings: Vec<LineString>,
}

impl ToJson for MultiLineString {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Pos>> =
            self.line_strings.iter().map(|l| l.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiLineString".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Polygon
///
/// [GeoJSON Format Specification § 2.1.6](http://geojson.org/geojson-spec.html#polygon)
pub struct Polygon {
    pub exterior: Vec<Pos>,
    pub holes: Option<Vec<Vec<Pos>>>,
}

impl Polygon {
    fn coordinates(&self) -> Vec<Vec<Pos>> {
        match self.holes {
            None => vec![self.exterior.clone()],
            Some(ref holes) => {
                let mut coordinates = holes.clone();
                coordinates.insert(0, self.exterior.clone());
                coordinates
            }
        }
    }
}

impl ToJson for Polygon {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Polygon".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates().to_json());
        d.to_json()
    }
}

/// MultiPolygon
///
/// [GeoJSON Format Specification § 2.1.7](http://geojson.org/geojson-spec.html#multipolygon)
pub struct MultiPolygon {
    pub polygons: Vec<Polygon>,
}

impl ToJson for MultiPolygon {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Vec<Pos>>> =
            self.polygons.iter().map(|p| p.coordinates()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPolygon".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Geometry
pub enum Geometry {
    Point(Point),
    MultiPoint(MultiPoint),
    LineString(LineString),
    MultiLineString(MultiLineString),
    Polygon(Polygon),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl ToJson for Geometry {
    fn to_json(&self) -> json::Json {
        match *self {
            Geometry::Point(ref geom) => geom.to_json(),
            Geometry::MultiPoint(ref geom) => geom.to_json(),
            Geometry::LineString(ref geom) => geom.to_json(),
            Geometry::MultiLineString(ref geom) => geom.to_json(),
            Geometry::Polygon(ref geom) => geom.to_json(),
            Geometry::MultiPolygon(ref geom) => geom.to_json(),
            Geometry::GeometryCollection(ref geom) => geom.to_json(),
        }
    }
}

/// GeometryCollection
///
/// [GeoJSON Format Specification § 2.1.8](http://geojson.org/geojson-spec.html#geometry-collection)
pub struct GeometryCollection {
    geometries: Vec<Geometry>,
}

impl ToJson for GeometryCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "GeometryCollection".to_string().to_json());
        d.insert("geometries".to_string(), self.geometries.to_json());
        d.to_json()
    }
}

/// Feature
///
/// [GeoJSON Format Specification § 2.2](http://geojson.org/geojson-spec.html#feature-objects)
pub struct Feature {
    geometry: Geometry,
    properties: json::Json,
}

impl ToJson for Feature {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Feature".to_string().to_json());
        d.insert("geometry".to_string(), self.geometry.to_json());
        d.insert("properties".to_string(), self.properties.to_json());
        d.to_json()
    }
}

/// FeatureCollection
///
/// [GeoJSON Format Specification § 2.3](http://geojson.org/geojson-spec.html#feature-collection-objects)
pub struct FeatureCollection {
    features: Vec<Feature>,
}

impl ToJson for FeatureCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "FeatureCollection".to_string().to_json());
        d.insert("features".to_string(), self.features.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {coordinates: Pos(vec![1., 2., 3.])};

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<commit_msg>beginning of ToGeoJson trait<commit_after>// TODO
// generic number instead of f64 for position?

extern crate serialize;

use std::collections::TreeMap;
use serialize::json::ToJson;
use serialize::json;

/// ToGeoJson
pub trait ToGeoJson {
    // TODO: change this to return a generic GeoJSON object
    fn to_geojson(&self) -> Geometry;
}

/// Pos (alias for Positions)
///
/// [GeoJSON Format Specification § 2.1.1](http://geojson.org/geojson-spec.html#positions)
pub struct Pos(pub Vec<f64>);

impl ToJson for Pos {
    fn to_json(&self) -> json::Json {
        let &Pos(ref nums) = self;
        nums.to_json()
    }
}

impl Clone for Pos {
    fn clone(&self) -> Pos {
        let &Pos(ref nums) = self;
        Pos(nums.clone())
    }
}

/// Point
///
/// [GeoJSON Format Specification § 2.1.2](http://geojson.org/geojson-spec.html#point)
pub struct Point {
    pub coordinates: Pos,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiPoint
///
/// [GeoJSON Format Specification § 2.1.3](http://geojson.org/geojson-spec.html#multipoint)
pub struct MultiPoint {
    pub points: Vec<Point>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Pos> =
            self.points.iter().map(|p| p.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// LineString
///
/// [GeoJSON Format Specification § 2.1.4](http://geojson.org/geojson-spec.html#linestring)
pub struct LineString {
    pub coordinates: Vec<Pos>,
}

impl ToJson for LineString {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "LineString".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiLineString
///
/// [GeoJSON Format Specification § 2.1.5](http://geojson.org/geojson-spec.html#multilinestring)
pub struct MultiLineString {
    pub line_strings: Vec<LineString>,
}

impl ToJson for MultiLineString {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Pos>> =
            self.line_strings.iter().map(|l| l.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiLineString".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Polygon
///
/// [GeoJSON Format Specification § 2.1.6](http://geojson.org/geojson-spec.html#polygon)
pub struct Polygon {
    pub exterior: Vec<Pos>,
    pub holes: Option<Vec<Vec<Pos>>>,
}

impl Polygon {
    fn coordinates(&self) -> Vec<Vec<Pos>> {
        match self.holes {
            None => vec![self.exterior.clone()],
            Some(ref holes) => {
                let mut coordinates = holes.clone();
                coordinates.insert(0, self.exterior.clone());
                coordinates
            }
        }
    }
}

impl ToJson for Polygon {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Polygon".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates().to_json());
        d.to_json()
    }
}

/// MultiPolygon
///
/// [GeoJSON Format Specification § 2.1.7](http://geojson.org/geojson-spec.html#multipolygon)
pub struct MultiPolygon {
    pub polygons: Vec<Polygon>,
}

impl ToJson for MultiPolygon {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Vec<Pos>>> =
            self.polygons.iter().map(|p| p.coordinates()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPolygon".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Geometry
pub enum Geometry {
    Point(Point),
    MultiPoint(MultiPoint),
    LineString(LineString),
    MultiLineString(MultiLineString),
    Polygon(Polygon),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl ToJson for Geometry {
    fn to_json(&self) -> json::Json {
        match *self {
            Geometry::Point(ref geom) => geom.to_json(),
            Geometry::MultiPoint(ref geom) => geom.to_json(),
            Geometry::LineString(ref geom) => geom.to_json(),
            Geometry::MultiLineString(ref geom) => geom.to_json(),
            Geometry::Polygon(ref geom) => geom.to_json(),
            Geometry::MultiPolygon(ref geom) => geom.to_json(),
            Geometry::GeometryCollection(ref geom) => geom.to_json(),
        }
    }
}

/// GeometryCollection
///
/// [GeoJSON Format Specification § 2.1.8](http://geojson.org/geojson-spec.html#geometry-collection)
pub struct GeometryCollection {
    geometries: Vec<Geometry>,
}

impl ToJson for GeometryCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "GeometryCollection".to_string().to_json());
        d.insert("geometries".to_string(), self.geometries.to_json());
        d.to_json()
    }
}

/// Feature
///
/// [GeoJSON Format Specification § 2.2](http://geojson.org/geojson-spec.html#feature-objects)
pub struct Feature {
    geometry: Geometry,
    properties: json::Json,
}

impl ToJson for Feature {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Feature".to_string().to_json());
        d.insert("geometry".to_string(), self.geometry.to_json());
        d.insert("properties".to_string(), self.properties.to_json());
        d.to_json()
    }
}

/// FeatureCollection
///
/// [GeoJSON Format Specification § 2.3](http://geojson.org/geojson-spec.html#feature-collection-objects)
pub struct FeatureCollection {
    features: Vec<Feature>,
}

impl ToJson for FeatureCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "FeatureCollection".to_string().to_json());
        d.insert("features".to_string(), self.features.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {coordinates: Pos(vec![1., 2., 3.])};

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<|endoftext|>