<commit_before>extern crate rustc_serialize;
extern crate docopt;
extern crate num;

use std::collections::HashSet;
use docopt::Docopt;

const USAGE: &'static str = "
rust-euler

Rust implementations of the Project Euler problems.

Usage: rust-euler [options]

Options:
	-p, --problem=K    Which Project Euler problem to solve [default: 1]
	-h, --help         Display this help and exit
";

#[derive(Debug, RustcDecodable)]
struct Args {
	flag_problem: u8,
	flag_help: bool,
}

fn main() {
	let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
									   .unwrap_or_else(|e| e.exit());
	let mut problem : fn() -> (u64, String);
	match args.flag_problem {
		1 => problem = problem_1,
		2 => problem = problem_2,
		3 => problem = problem_3,
		_ => problem = problem_not_supported,
	}
	let (result, message) = problem();
	println!("{}", message);
	println!("{}", result);
}

fn problem_1() -> (u64, String) {
	let mut multiples = HashSet::new();
	for i in num::range_step(3, 1000, 3) {
		multiples.insert(i);
	}
	for i in num::range_step(5, 1000, 5) {
		multiples.insert(i);
	}
	let sum = multiples.iter().fold(0, |sum, x| sum + x);
	return (sum, "".to_string());
}

fn problem_2() -> (u64, String) {
	let mut current = 2;
	let mut previous = 1;
	let mut n = 0;
	let mut sum = 2;
	while current < 4000000 {
		let temp = current;
		current = temp + previous;
		previous = temp;
		n = n + 1;
		if n == 3 {
			sum += current;
			n = 0;
		}
	}
	return (sum, "".to_string());
}

/* A number is prime if it is divisble by no numbers other than 2 or itself.
   Our naive prime checking function performs this check.
   However we know that if a number x is not divisble by a number i
   it is not divisible by any multiples of i.
   So really the check to see if a number is prime is to divide by all primes
   less than that number.

*/

fn is_prime(x: u64) -> bool {
	let mut i = 2;
	while i < (x / 2) {
		if x % i == 0 {
			return false;
		}
		i += 1;
	}
	return true;
}

fn problem_3() -> (u64, String) {
	 let a : u64 = 600851475143;
	 let mut d = 2;
	 while d < (a / 2) {
	 	// Check that the result is an integer
	 	if a % d == 0 {
	 		match is_prime(a / d) {
	 			true => {return (a / d, "".to_string());},
	 			false => {}
	 		}
	 	}
	 	d += 1;
	 }
	 return (a, "Failed to find any prime factors - the number must be prime.".to_string())
}

fn problem_not_supported() -> (u64, String) {
	return (0, "Problem number solution not supported".to_string());
}<commit_msg>Change problem functions to not allocate memory for return strings (these are now statically stored)<commit_after>extern crate rustc_serialize;
extern crate docopt;
extern crate num;

use std::collections::HashSet;
use docopt::Docopt;

const USAGE: &'static str = "
rust-euler

Rust implementations of the Project Euler problems.

Usage: rust-euler [options]

Options:
	-p, --problem=K    Which Project Euler problem to solve [default: 1]
	-h, --help         Display this help and exit
	-b, --bench        Benchmark the specified problem
";

const DEFAULT_RETURN: &'static str = "The problem solution algorithm completed. The reported answer is: ";
const ERROR_PROBLEM_NOT_IMPL: &'static str = "Problem number solution not supported";

#[derive(Debug, RustcDecodable)]
struct Args {
	flag_problem: u8,
	flag_help: bool,
	flag_bench: bool,
}

fn main() {
	let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
									   .unwrap_or_else(|e| e.exit());
	let mut problem : fn() -> (u64, &'static str);
	match args.flag_problem {
		1 => problem = problem_1,
		2 => problem = problem_2,
		3 => problem = problem_3,
		_ => problem = problem_not_supported,
	}
	let (result, message) = problem();
	println!("{}", message);
	println!("{}", result);
}

fn problem_1() -> (u64, &'static str) {
	let mut multiples = HashSet::new();
	for i in num::range_step(3, 1000, 3) {
		multiples.insert(i);
	}
	for i in num::range_step(5, 1000, 5) {
		multiples.insert(i);
	}
	let sum = multiples.iter().fold(0, |sum, x| sum + x);
	return (sum, DEFAULT_RETURN);
}

fn problem_2() -> (u64, &'static str) {
	let mut current = 2;
	let mut previous = 1;
	let mut n = 0;
	let mut sum = 2;
	while current < 4000000 {
		let temp = current;
		current = temp + previous;
		previous = temp;
		n = n + 1;
		if n == 3 {
			sum += current;
			n = 0;
		}
	}
	return (sum, DEFAULT_RETURN);
}

/* A number is prime if it is divisble by no numbers other than 2 or itself.
   Our naive prime checking function performs this check.
   However we know that if a number x is not divisble by a number i
   it is not divisible by any multiples of i.
   So really the check to see if a number is prime is to divide by all primes
   less than that number.
*/

fn is_prime(x : u64) -> bool {
	let mut i = 2;
	while i < (x / 2) {
		if x % i == 0 {
			return false;
		}
		i += 1;
	}
	return true;
}

fn problem_3() -> (u64, &'static str) {
	 let a : u64 = 600851475143;
	 let mut d = 2;
	 while d < (a / 2) {
	 	// Check that the result is an integer
	 	if a % d == 0 {
	 		match is_prime(a / d) {
	 			true => {return (a / d, DEFAULT_RETURN);},
	 			false => {}
	 		}
	 	}
	 	d += 1;
	 }
	 return (a, DEFAULT_RETURN);
}

fn problem_not_supported() -> (u64, &'static str) {
	return (0, ERROR_PROBLEM_NOT_IMPL);
}<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .ok()
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}
<commit_msg>Comparing guesses<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .ok()
        .expect("Failed to read line");

    let guess: u32 = guess.trim().parse()
        .ok()
        .expect("Please type a number!");

    println!("You guessed: {}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less      => println!("Too small!"),
        Ordering::Greater   => println!("Too big!"),
        Ordering::Equal     => println!("You win!"),
    }
}
<|endoftext|>


<commit_before>extern crate markdown;
extern crate getopts;
use getopts::{optopt,optflag,getopts,OptGroup, usage, short_usage, Matches};
use std::os;
use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;

fn build(matches: Matches) {
    let source = match matches.opt_str("s"){
        Some(x) => Path::new(x),
        None => Path::new("./")
    };

    println!("Printing out {}", source.display());

    let dest = Path::new("./_site/");
    fs::mkdir(&dest, io::USER_RWX);

    match copy_recursive(&source, &dest, |p| -> bool {
        !p.filename_str().unwrap().starts_with(".") &&
        !(p.path_relative_from(&source).unwrap().as_str().unwrap() == "articles")
    })  {
        Err(why) => println!("! {}", why.kind),
        _ => {}
    }

    println!("Testing markdown integration");
    let text = markdown::to_html("This is a *text*");
    println!("{}", text);
}

fn copy_recursive(source: &Path, dest: &Path, valid: |&Path| -> bool) -> io::IoResult<()> {
    if source.is_dir() {
        let contents = try!(fs::readdir(source));
        for entry in contents.iter() {
            if entry.is_dir() {
                if valid(entry) {
                    let new_dest = &dest.join(entry.path_relative_from(source).unwrap());
                    fs::mkdir(new_dest, io::USER_RWX);
                    try!(copy_recursive(entry, new_dest, |p| valid(p)));
                }
            } else {
                if valid(entry) {
                    try!(fs::copy(entry, &dest.join(entry.path_relative_from(source).unwrap())));
                }
            }
        }
        Ok(())
    } else {
        Err(io::standard_error(io::InvalidInput))
    }
}

fn main() {

    let opts = [
        optopt("d", "destination", "set destination directory", "NAME"),
        optopt("s", "source", "set source directory", "NAME"),
        optflag("h", "help", "print this help menu")
    ];

    let instructions = "Usage: lava [command] ";

    let args = os::args();
    let program = args[0].clone();

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    };

    if matches.opt_present("h") {
        println!("{}", usage(program.as_slice(), opts));
        return;
    }

    let command = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("{}", short_usage(instructions, opts));
        return;
    };

    match command.as_slice()  {
        "build" => build(matches),
        _ => {
            println!("{}", short_usage(instructions, opts));
            return;
        }
    }
}

<commit_msg>walk pages<commit_after>extern crate markdown;
extern crate getopts;

use getopts::{optopt,optflag,getopts, usage, short_usage, Matches};
use std::os;
use std::io;
use std::io::fs;
use std::io::File;
use std::io::fs::PathExtensions;

fn build(matches: Matches) {
    let source = match matches.opt_str("s"){
        Some(x) => Path::new(x),
        None => Path::new("./")
    };

    let dest = match matches.opt_str("d"){
        Some(x) => Path::new(x),
        None => Path::new("./_site/")
    };

    println!("Generating from {} to {}", source.display(), dest.display());

    fs::mkdir(&dest, io::USER_RWX);

    match fs::walk_dir(&source.join("_pages")) {
        Err(why) => println!("! {}", why.detail),
        Ok(mut paths) => for path in paths {
            render_file(&path);
        }
    }

    if source != dest {
        match copy_recursive(&source, &dest, |p| -> bool {
            !p.filename_str().unwrap().starts_with(".") &&
            !(p.path_relative_from(&source).unwrap().as_str().unwrap() == "articles")
        }) {
            Err(why) => println!("! {}", why.detail),
            _ => {}
        }
    }

    println!("Testing markdown integration");
    let text = markdown::to_html("This is a *text*");
    println!("{}", text);

    println!("Done");
}

fn render_file(path : &Path) {
    let mut file = File::open(path);
    let content = match file.read_to_string(){
        Ok(x) => x,
        Err(e) => {
            println!("Could not read file {} : {}", path.display(), e)
            return;
        }
    };
    println!("{}", content);
}

fn copy_recursive(source: &Path, dest: &Path, valid: |&Path| -> bool) -> io::IoResult<()> {
    if source.is_dir() {
        let contents = try!(fs::readdir(source));
        for entry in contents.iter() {
            if entry.is_dir() {
                if valid(entry) {
                    let new_dest = &dest.join(entry.path_relative_from(source).unwrap());
                    fs::mkdir(new_dest, io::USER_RWX);
                    try!(copy_recursive(entry, new_dest, |p| valid(p)));
                }
            } else {
                if valid(entry) {
                    try!(fs::copy(entry, &dest.join(entry.path_relative_from(source).unwrap())));
                }
            }
        }
        Ok(())
    } else {
        Err(io::standard_error(io::InvalidInput))
    }
}

fn main() {

    let opts = [
        optopt("d", "destination", "set destination directory", "NAME"),
        optopt("s", "source", "set source directory", "NAME"),
        optflag("h", "help", "print this help menu")
    ];

    let instructions = "Usage: lava [command] ";

    let args = os::args();
    let program = args[0].clone();

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    };

    if matches.opt_present("h") {
        println!("{}", usage(program.as_slice(), opts));
        return;
    }

    let command = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("{}", short_usage(instructions, opts));
        return;
    };

    match command.as_slice()  {
        "build" => build(matches),
        _ => {
            println!("{}", short_usage(instructions, opts));
            return;
        }
    }
}

<|endoftext|>


<commit_before>extern crate libc;

use libc::funcs::posix88::unistd::execvp;
use std::c_str::CString;
use std::os::last_os_error;
use std::ptr;
use std::rand::Rng;

fn main() {
    let version = "0.1.0";
    match parse_args(&std::os::args()) {
        Err(Usage) => {
            std::os::set_exit_status(1);
            print_usage(version);
        }
        Err(Help) =>
            print_usage(version),
        Err(Version) =>
            print_version(version),
        Ok(opts) => {
            if whack(&opts) {
                std::os::set_exit_status(1);
            } else {
                opts.exe.map_or((), |exe| {
                    execvp_easy(&exe.name.to_string(), exe.args)
                });
            }
        }
    }
}

type ArgParse<T> = Result<T, Usage>;

#[deriving(Show)]
struct Options {
    chance: int,
    exe: Option<Exe>,
}

#[deriving(Show)]
struct Exe {
    name: String,
    args: Box<Vec<String>>,
}

#[deriving(Show)]
enum Usage {
    Usage,
    Help,
    Version,
}

trait Uncons<'a, T> {
    fn uncons(&self) -> Option<(&'a T, &'a [T])>;
}

impl<'a, T> Uncons<'a, T> for &'a [T] {
    fn uncons(&self) -> Option<(&'a T, &'a [T])> {
        self.head().map(|x| (x, self.tail()))
    }
}

fn parse_args(args: &Vec<String>) -> ArgParse<Options> {
    args.as_slice().tail().uncons().map_or(Err(Usage), |(s, args)| {
        if ["--help".to_string(), "-h".to_string()].contains(s) {
            Err(Help)
        } else if ["--version".to_string(), "-v".to_string()].contains(s) {
            Err(Version)
        } else if ["--chance".to_string(), "-c".to_string()].contains(s) {
            args.uncons().map_or(Err(Usage), |(s, args)| {
                from_str::<int>(s.as_slice()).map_or(Err(Usage), |val| {
                    args.uncons().map_or(Ok(Options { chance: val, exe: None }), |(exe, args)| {
                        if "--".to_string() == exe.to_string() {
                            args.uncons().map_or(Ok(Options { chance: val, exe: None }), |(exe, args)| {
                                Ok(Options {
                                    chance: val,
                                    exe: Some(Exe {
                                        name: exe.to_string(),
                                        args: box std::vec::Vec::from_slice(args),
                                    })
                                })
                            })
                        } else {
                            Ok(Options {
                                chance: val,
                                exe: Some(Exe {
                                    name: exe.to_string(),
                                    args: box std::vec::Vec::from_slice(args),
                                })
                            })
                        }
                    })
                })
            })
        } else {
            Err(Usage)
        }
    })
}

fn whack(opts: &Options) -> bool {
    std::rand::task_rng().gen_range(0, 100) > std::cmp::min(std::cmp::max(opts.chance, 0), 100)
}

fn execvp_easy(name: &String, args: &Vec<String>) {
    let c_name: CString = name.to_c_str();
    let c_args: Vec<CString> = args.iter().map(|tmp| tmp.to_c_str()).collect();
    with_argv(&c_name, c_args.as_slice(), proc(c_argv) -> () unsafe {
        execvp(*c_argv, c_argv);
        fail!("executing {}: {}", name, std::os::last_os_error());
    });
}

fn with_argv<T>(prog: &CString, args: &[CString], f: proc(**libc::c_char) -> T) -> T {
    let mut ptrs: Vec<*libc::c_char> = Vec::with_capacity(args.len() + 1);

    ptrs.push(prog.with_ref(|buf| buf));
    ptrs.extend(args.iter().map(|tmp| tmp.with_ref(|buf| buf)));
    ptrs.push(ptr::null());

    f(ptrs.as_ptr())
}

fn print_usage(version: &str) {
    print_version(version);
    println!("\n\
        Usage: whacky (-c PERCENTAGE|--chance PERCENTAGE) [[--] COMMAND]\n\
          whacky, yet another randomly failing program\n\
        \n\
        Available options:\n\
          -h,--help           show this help text\n\
          -c,--chance         set success chance");
}

fn print_version(version: &str) {
    println!("whacky {}", version);
}
<commit_msg>Fix compilation with the latest nightly build<commit_after>extern crate libc;

use libc::funcs::posix88::unistd::execvp;
use std::c_str::CString;
use std::os::last_os_error;
use std::ptr;
use std::rand::Rng;

fn main() {
    let version = "0.1.0";
    match parse_args(&std::os::args()) {
        Err(Usage) => {
            std::os::set_exit_status(1);
            print_usage(version);
        }
        Err(Help) =>
            print_usage(version),
        Err(Version) =>
            print_version(version),
        Ok(opts) => {
            if whack(&opts) {
                std::os::set_exit_status(1);
            } else {
                opts.exe.map_or((), |exe| {
                    execvp_easy(&exe.name.to_string(), exe.args)
                });
            }
        }
    }
}

type ArgParse<T> = Result<T, Usage>;

#[deriving(Show)]
struct Options {
    chance: int,
    exe: Option<Exe>,
}

#[deriving(Show)]
struct Exe {
    name: String,
    args: Box<Vec<String>>,
}

#[deriving(Show)]
enum Usage {
    Usage,
    Help,
    Version,
}

trait Uncons<'a, T> {
    fn uncons(&self) -> Option<(&'a T, &'a [T])>;
}

impl<'a, T> Uncons<'a, T> for &'a [T] {
    fn uncons(&self) -> Option<(&'a T, &'a [T])> {
        self.head().map(|x| (x, self.tail()))
    }
}

fn parse_args(args: &Vec<String>) -> ArgParse<Options> {
    args.as_slice().tail().uncons().map_or(Err(Usage), |(s, args)| {
        if ["--help".to_string(), "-h".to_string()].contains(s) {
            Err(Help)
        } else if ["--version".to_string(), "-v".to_string()].contains(s) {
            Err(Version)
        } else if ["--chance".to_string(), "-c".to_string()].contains(s) {
            args.uncons().map_or(Err(Usage), |(s, args)| {
                from_str::<int>(s.as_slice()).map_or(Err(Usage), |val| {
                    args.uncons().map_or(Ok(Options { chance: val, exe: None }), |(exe, args)| {
                        if "--".to_string() == exe.to_string() {
                            args.uncons().map_or(Ok(Options { chance: val, exe: None }), |(exe, args)| {
                                Ok(Options {
                                    chance: val,
                                    exe: Some(Exe {
                                        name: exe.to_string(),
                                        args: box std::vec::Vec::from_slice(args),
                                    })
                                })
                            })
                        } else {
                            Ok(Options {
                                chance: val,
                                exe: Some(Exe {
                                    name: exe.to_string(),
                                    args: box std::vec::Vec::from_slice(args),
                                })
                            })
                        }
                    })
                })
            })
        } else {
            Err(Usage)
        }
    })
}

fn whack(opts: &Options) -> bool {
    std::rand::task_rng().gen_range(0, 100) > std::cmp::min(std::cmp::max(opts.chance, 0), 100)
}

fn execvp_easy(name: &String, args: Box<Vec<String>>) {
    let c_name: CString = name.to_c_str();
    let c_args: Vec<CString> = args.iter().map(|tmp| tmp.to_c_str()).collect();
    with_argv(&c_name, c_args.as_slice(), proc(c_argv) -> () unsafe {
        execvp(*c_argv, c_argv);
        fail!("executing {}: {}", name, std::os::last_os_error());
    });
}

fn with_argv<T>(prog: &CString, args: &[CString], f: proc(*mut*const libc::c_char) -> T) -> T {
    let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len() + 1);

    ptrs.push(prog.as_ptr());
    ptrs.extend(args.iter().map(|tmp| tmp.as_ptr()));
    ptrs.push(ptr::null());

    f(ptrs.as_mut_ptr())
}

fn print_usage(version: &str) {
    print_version(version);
    println!("\n\
        Usage: whacky (-c PERCENTAGE|--chance PERCENTAGE) [[--] COMMAND]\n\
          whacky, yet another randomly failing program\n\
        \n\
        Available options:\n\
          -h,--help           show this help text\n\
          -c,--chance         set success chance");
}

fn print_version(version: &str) {
    println!("whacky {}", version);
}
<|endoftext|>


<commit_before>#![feature(io, os, path, core)]

extern crate lines;

use std::os;
use std::old_io::{BufferedReader, File, IoResult};
use lines::linemapper;

fn main() {
    for arg in os::args().iter().skip(1) {
        match process_arg(arg) {
            Ok(lines) => println!("{}: {}", arg, lines),
            Err(e) => println!("{}: {}", arg, e),
        }
    }
}

fn process_arg(arg: &String) -> IoResult<usize> {
    let f = try!(File::open(&Path::new(arg)));
    linemapper::count_lines(BufferedReader::new(f))
}
<commit_msg>Favor env::args() over os::args()<commit_after>#![feature(io, path, core, env, os)]

extern crate lines;

use std::env;
use std::old_io::{BufferedReader, File, IoResult};
use lines::linemapper;

fn main() {
    for arg in env::args().skip(1) {
        let arg = arg.into_string().unwrap();
        match process_arg(&arg) {
            Ok(lines) => println!("{}: {}", arg, lines),
            Err(e) => println!("{}: {}", arg, e),
        }
    }
}

fn process_arg(arg: &String) -> IoResult<usize> {
    let f = try!(File::open(&Path::new(arg)));
    linemapper::count_lines(BufferedReader::new(f))
}
<|endoftext|>


<commit_before>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize * 3;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, _, x, y) => {
        let ww = WINDOW_WIDTH as f32;
        let wh = WINDOW_HEIGHT as f32;
        mdlbt.low_x = (x as f32) / ww * mdlbt.width + mdlbt.low_x;
        mdlbt.low_y = (y as f32) / wh * mdlbt.height + mdlbt.low_y;
        mdlbt.width = mdlbt.width / ww;
        mdlbt.height = mdlbt.height / wh;

        timers.time("update", || {
          vao.buffer.update(gl, 0, mdlbt.render().as_slice());
        });
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          if key == KeyCode::Up {
            mdlbt.max_iter *= 2;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          } else if key == KeyCode::Down {
            mdlbt.max_iter /= 2;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
        }
      },
      _ => {},
    }
  }
}
<commit_msg>Only left-click zooms<commit_after>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize * 3;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f32;
            let wh = WINDOW_HEIGHT as f32;
            mdlbt.low_x = (x as f32) / ww * mdlbt.width + mdlbt.low_x;
            mdlbt.low_y = (y as f32) / wh * mdlbt.height + mdlbt.low_y;
            mdlbt.width = mdlbt.width / ww;
            mdlbt.height = mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
#[macro_use]
extern crate clap;
extern crate ucglib;

use std::cell::RefCell;
use std::error::Error;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::process;
use std::rc::Rc;

use ucglib::build;
use ucglib::build::assets::{Cache, MemoryCache};
use ucglib::build::Val;
use ucglib::convert::traits;
use ucglib::convert::ConverterRegistry;

// TODO(jwall): List the target output types automatically.
fn do_flags<'a, 'b>() -> clap::App<'a, 'b> {
    clap_app!(
        ucg =>
            (version: crate_version!())
            (author: crate_authors!())
            (about: "Universal Configuration Grammar compiler.")
            (@subcommand inspect =>
             (about: "Inspect a specific symbol in a ucg file.")
             (@arg sym: --sym +takes_value +required "Specify a specific binding in the ucg file to output.")
             (@arg target: --format +required +takes_value "Inspect output type. (flags, json, env, exec)")
             (@arg INPUT: +required "Input ucg file to inspect symbol from.")
            )
            (@subcommand build =>
             (about: "Build a list of ucg files.")
             (@arg recurse: -r +required conflicts_with[INPUT] "Whether we should recurse in directories or not.")
             (@arg INPUT: ... "Input ucg files or directories to build. If not provided then build the contents of the current directory.")
            )
            (@subcommand test =>
             (about: "Check a list of ucg files for errors and run test assertions.")
             (@arg recurse: -r +required conflicts_with[INPUT] "Whether we should recurse or not.")
             (@arg INPUT: ... "Input ucg files or directories to run test assertions for. If not provided it will scan the current directory for files with _test.ucg")
            )
            (@subcommand converters =>
             (about: "list the available converters")
            )
    )
}

fn run_converter(c: &traits::Converter, v: Rc<Val>, f: Option<&str>) -> traits::Result {
    let mut file: Box<std::io::Write> = match f {
        Some(f) => {
            let mut path_buf = PathBuf::from(f);
            path_buf.set_extension(c.file_ext());
            let new_path = path_buf.to_str().unwrap();
            Box::new(try!(File::create(&new_path)))
        }
        None => Box::new(io::stdout()),
    };
    c.convert(v, file.as_mut())
}

fn build_file(
    file: &str,
    validate: bool,
    cache: Rc<RefCell<Cache>>,
) -> Result<build::Builder, Box<Error>> {
    let mut root = PathBuf::from(file);
    if root.is_relative() {
        root = std::env::current_dir().unwrap().join(root);
    }
    let mut builder = build::Builder::new(root.parent().unwrap(), cache);
    if validate {
        builder.enable_validate_mode();
    }
    try!(builder.build_file(file));
    if validate {
        println!("{}", builder.assert_collector.summary);
    }
    Ok(builder)
}

fn do_validate(file: &str, cache: Rc<RefCell<Cache>>) -> bool {
    println!("Validating {}", file);
    match build_file(file, true, cache) {
        Ok(b) => {
            if b.assert_collector.success {
                println!("File {} Pass\n", file);
            } else {
                println!("File {} Fail\n", file);
                return false;
            }
        }
        Err(msg) => {
            eprintln!("Err: {}", msg);
            return false;
        }
    }
    return true;
}

fn do_compile(file: &str, cache: Rc<RefCell<Cache>>, registry: &ConverterRegistry) -> bool {
    println!("Building {}", file);
    let builder = match build_file(file, false, cache.clone()) {
        Ok(builder) => builder,
        Err(err) => {
            eprintln!("{}", err);
            return false;
        }
    };
    let (typ, val) = match builder.out_lock {
        Some((ref typ, ref val)) => (typ, val.clone()),
        None => {
            eprintln!("Build results in no artifacts.");
            return false;
        }
    };
    match registry.get_converter(typ) {
        Some(converter) => {
            run_converter(converter, val, Some(file)).unwrap();
            eprintln!("Build successful");
            return true;
        }
        None => {
            eprintln!("No such converter {}", typ);
            return false;
        }
    }
}

fn visit_ucg_files(
    path: &Path,
    recurse: bool,
    validate: bool,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) -> Result<bool, Box<Error>> {
    let our_path = String::from(path.to_string_lossy());
    let mut result = true;
    // TODO(jwall): Report the failing files at the bottom.
    let mut summary = String::new();
    if path.is_dir() {
        let mut dir_iter = try!(std::fs::read_dir(path)).peekable();
        loop {
            let entry = match dir_iter.next() {
                Some(e) => e,
                None => {
                    break;
                }
            };
            let next_item = try!(entry);
            let next_path = next_item.path();
            let path_as_string = String::from(next_path.to_string_lossy());
            if next_path.is_dir() && recurse {
                if let Err(e) =
                    visit_ucg_files(&next_path, recurse, validate, cache.clone(), registry)
                {
                    eprintln!("{}", e);
                    result = false;
                }
            } else {
                if validate && path_as_string.ends_with("_test.ucg") {
                    if !do_validate(&path_as_string, cache.clone()) {
                        result = false;
                        summary.push_str(format!("{} - FAIL\n", path_as_string).as_str())
                    } else {
                        summary.push_str(format!("{} - PASS\n", path_as_string).as_str())
                    }
                } else if !validate && path_as_string.ends_with(".ucg") {
                    if !do_compile(&path_as_string, cache.clone(), registry) {
                        result = false;
                    }
                }
            }
        }
    } else if validate && our_path.ends_with("_test.ucg") {
        if !do_validate(&our_path, cache) {
            result = false;
            summary.push_str(format!("{} - FAIL\n", our_path).as_str());
        } else {
            summary.push_str(format!("{} - PASS\n", &our_path).as_str());
        }
    } else if !validate {
        if !do_compile(&our_path, cache, registry) {
            result = false;
        }
    }
    if validate && !summary.is_empty() {
        println!("RESULTS:");
        println!("{}", summary);
    }
    Ok(result)
}

fn inspect_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) {
    let file = matches.value_of("INPUT").unwrap();
    let sym = matches.value_of("sym");
    let target = matches.value_of("target").unwrap();
    let root = PathBuf::from(file);
    let mut builder = build::Builder::new(root.parent().unwrap(), cache);
    match registry.get_converter(target) {
        Some(converter) => {
            // TODO(jwall): We should warn if this is a test file.
            let result = builder.build_file(file);
            if !result.is_ok() {
                eprintln!("{:?}", result.err().unwrap());
                process::exit(1);
            }
            let val = match sym {
                Some(sym_name) => builder.get_out_by_name(sym_name),
                None => builder.last,
            };
            match val {
                Some(value) => {
                    // We use None here because we always output to stdout for an inspect.
                    run_converter(converter, value, None).unwrap();
                    eprintln!("Build successful");
                    process::exit(0);
                }
                None => {
                    eprintln!("Build results in no value.");
                    process::exit(1);
                }
            }
        }
        None => {
            eprintln!("No such converter {}", target);
            process::exit(1);
        }
    }
}

fn build_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) {
    let files = matches.values_of("INPUT");
    let recurse = matches.is_present("recurse");
    let mut ok = true;
    if files.is_none() {
        let curr_dir = std::env::current_dir().unwrap();
        let ok = visit_ucg_files(curr_dir.as_path(), recurse, false, cache.clone(), &registry);
        if let Ok(false) = ok {
            process::exit(1)
        }
        process::exit(0);
    }
    for file in files.unwrap() {
        let pb = PathBuf::from(file);
        if let Ok(false) = visit_ucg_files(&pb, recurse, false, cache.clone(), &registry) {
            ok = false;
        }
    }
    if !ok {
        process::exit(1)
    }
}

fn test_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) {
    let files = matches.values_of("INPUT");
    let recurse = matches.is_present("recurse");
    if files.is_none() {
        let curr_dir = std::env::current_dir().unwrap();
        let ok = visit_ucg_files(curr_dir.as_path(), recurse, true, cache.clone(), &registry);
        if let Ok(false) = ok {
            process::exit(1)
        }
    } else {
        let mut ok = true;
        for file in files.unwrap() {
            let pb = PathBuf::from(file);
            //if pb.is_dir() {
            if let Ok(false) =
                visit_ucg_files(pb.as_path(), recurse, true, cache.clone(), &registry)
            {
                ok = false;
            }
        }
        if !ok {
            process::exit(1)
        }
    }
    process::exit(0);
}

fn converters_command(registry: &ConverterRegistry) {
    println!("Available converters:");
    println!("");
    for (name, c) in registry.get_converter_list().iter() {
        println!("- {}", name);
        println!("  Description: {}", c.description());
        println!("  Output Extension: `.{}`", c.file_ext());
        println!("");
    }
}

fn main() {
    let mut app = do_flags();
    let app_matches = app.clone().get_matches();
    let cache: Rc<RefCell<Cache>> = Rc::new(RefCell::new(MemoryCache::new()));
    let registry = ConverterRegistry::make_registry();
    if let Some(matches) = app_matches.subcommand_matches("inspect") {
        inspect_command(matches, cache, &registry);
    } else if let Some(matches) = app_matches.subcommand_matches("build") {
        build_command(matches, cache, &registry);
    } else if let Some(matches) = app_matches.subcommand_matches("test") {
        test_command(matches, cache, &registry);
    } else if let Some(_) = app_matches.subcommand_matches("converters") {
        converters_command(&registry)
    } else {
        app.print_help().unwrap();
        println!("");
    }
}
<commit_msg>FEATURE: Use a command line flag to turn off strict mode.<commit_after>// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
#[macro_use]
extern crate clap;
extern crate ucglib;

use std::cell::RefCell;
use std::error::Error;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::process;
use std::rc::Rc;

use ucglib::build;
use ucglib::build::assets::{Cache, MemoryCache};
use ucglib::build::Val;
use ucglib::convert::traits;
use ucglib::convert::ConverterRegistry;

// TODO(jwall): List the target output types automatically.
fn do_flags<'a, 'b>() -> clap::App<'a, 'b> {
    clap_app!(
        ucg =>
            (version: crate_version!())
            (author: crate_authors!())
            (about: "Universal Configuration Grammar compiler.")
            (@arg nostrict: --("no-strict") "Turn off strict checking.")
            (@subcommand inspect =>
             (about: "Inspect a specific symbol in a ucg file.")
             (@arg sym: --sym +takes_value +required "Specify a specific binding in the ucg file to output.")
             (@arg target: --format +required +takes_value "Inspect output type. (flags, json, env, exec)")
             (@arg INPUT: +required "Input ucg file to inspect symbol from.")
            )
            (@subcommand build =>
             (about: "Build a list of ucg files.")
             (@arg recurse: -r +required conflicts_with[INPUT] "Whether we should recurse in directories or not.")
             (@arg INPUT: ... "Input ucg files or directories to build. If not provided then build the contents of the current directory.")
            )
            (@subcommand test =>
             (about: "Check a list of ucg files for errors and run test assertions.")
             (@arg recurse: -r +required conflicts_with[INPUT] "Whether we should recurse or not.")
             (@arg INPUT: ... "Input ucg files or directories to run test assertions for. If not provided it will scan the current directory for files with _test.ucg")
            )
            (@subcommand converters =>
             (about: "list the available converters")
            )
    )
}

fn run_converter(c: &traits::Converter, v: Rc<Val>, f: Option<&str>) -> traits::Result {
    let mut file: Box<std::io::Write> = match f {
        Some(f) => {
            let mut path_buf = PathBuf::from(f);
            path_buf.set_extension(c.file_ext());
            let new_path = path_buf.to_str().unwrap();
            Box::new(try!(File::create(&new_path)))
        }
        None => Box::new(io::stdout()),
    };
    c.convert(v, file.as_mut())
}

fn build_file(
    file: &str,
    validate: bool,
    strict: bool,
    cache: Rc<RefCell<Cache>>,
) -> Result<build::Builder, Box<Error>> {
    let mut root = PathBuf::from(file);
    if root.is_relative() {
        root = std::env::current_dir().unwrap().join(root);
    }
    let mut builder = build::Builder::new(root.parent().unwrap(), cache);
    builder.set_strict(strict);
    if validate {
        builder.enable_validate_mode();
    }
    try!(builder.build_file(file));
    if validate {
        println!("{}", builder.assert_collector.summary);
    }
    Ok(builder)
}

fn do_validate(file: &str, strict: bool, cache: Rc<RefCell<Cache>>) -> bool {
    println!("Validating {}", file);
    match build_file(file, true, strict, cache) {
        Ok(b) => {
            if b.assert_collector.success {
                println!("File {} Pass\n", file);
            } else {
                println!("File {} Fail\n", file);
                return false;
            }
        }
        Err(msg) => {
            eprintln!("Err: {}", msg);
            return false;
        }
    }
    return true;
}

fn do_compile(
    file: &str,
    strict: bool,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) -> bool {
    println!("Building {}", file);
    let builder = match build_file(file, false, strict, cache.clone()) {
        Ok(builder) => builder,
        Err(err) => {
            eprintln!("{}", err);
            return false;
        }
    };
    let (typ, val) = match builder.out_lock {
        Some((ref typ, ref val)) => (typ, val.clone()),
        None => {
            eprintln!("Build results in no artifacts.");
            return false;
        }
    };
    match registry.get_converter(typ) {
        Some(converter) => {
            run_converter(converter, val, Some(file)).unwrap();
            eprintln!("Build successful");
            return true;
        }
        None => {
            eprintln!("No such converter {}", typ);
            return false;
        }
    }
}

fn visit_ucg_files(
    path: &Path,
    recurse: bool,
    validate: bool,
    strict: bool,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
) -> Result<bool, Box<Error>> {
    let our_path = String::from(path.to_string_lossy());
    let mut result = true;
    // TODO(jwall): Report the failing files at the bottom.
    let mut summary = String::new();
    if path.is_dir() {
        let mut dir_iter = try!(std::fs::read_dir(path)).peekable();
        loop {
            let entry = match dir_iter.next() {
                Some(e) => e,
                None => {
                    break;
                }
            };
            let next_item = try!(entry);
            let next_path = next_item.path();
            let path_as_string = String::from(next_path.to_string_lossy());
            if next_path.is_dir() && recurse {
                if let Err(e) = visit_ucg_files(
                    &next_path,
                    recurse,
                    validate,
                    strict,
                    cache.clone(),
                    registry,
                ) {
                    eprintln!("{}", e);
                    result = false;
                }
            } else {
                if validate && path_as_string.ends_with("_test.ucg") {
                    if !do_validate(&path_as_string, strict, cache.clone()) {
                        result = false;
                        summary.push_str(format!("{} - FAIL\n", path_as_string).as_str())
                    } else {
                        summary.push_str(format!("{} - PASS\n", path_as_string).as_str())
                    }
                } else if !validate && path_as_string.ends_with(".ucg") {
                    if !do_compile(&path_as_string, strict, cache.clone(), registry) {
                        result = false;
                    }
                }
            }
        }
    } else if validate && our_path.ends_with("_test.ucg") {
        if !do_validate(&our_path, strict, cache) {
            result = false;
            summary.push_str(format!("{} - FAIL\n", our_path).as_str());
        } else {
            summary.push_str(format!("{} - PASS\n", &our_path).as_str());
        }
    } else if !validate {
        if !do_compile(&our_path, strict, cache, registry) {
            result = false;
        }
    }
    if validate && !summary.is_empty() {
        println!("RESULTS:");
        println!("{}", summary);
    }
    Ok(result)
}

fn inspect_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
    strict: bool,
) {
    let file = matches.value_of("INPUT").unwrap();
    let sym = matches.value_of("sym");
    let target = matches.value_of("target").unwrap();
    let root = PathBuf::from(file);
    let mut builder = build::Builder::new(root.parent().unwrap(), cache);
    builder.set_strict(strict);
    match registry.get_converter(target) {
        Some(converter) => {
            // TODO(jwall): We should warn if this is a test file.
            let result = builder.build_file(file);
            if !result.is_ok() {
                eprintln!("{:?}", result.err().unwrap());
                process::exit(1);
            }
            let val = match sym {
                Some(sym_name) => builder.get_out_by_name(sym_name),
                None => builder.last,
            };
            match val {
                Some(value) => {
                    // We use None here because we always output to stdout for an inspect.
                    run_converter(converter, value, None).unwrap();
                    eprintln!("Build successful");
                    process::exit(0);
                }
                None => {
                    eprintln!("Build results in no value.");
                    process::exit(1);
                }
            }
        }
        None => {
            eprintln!("No such converter {}", target);
            process::exit(1);
        }
    }
}

fn build_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
    strict: bool,
) {
    let files = matches.values_of("INPUT");
    let recurse = matches.is_present("recurse");
    let mut ok = true;
    if files.is_none() {
        let curr_dir = std::env::current_dir().unwrap();
        let ok = visit_ucg_files(
            curr_dir.as_path(),
            recurse,
            false,
            strict,
            cache.clone(),
            &registry,
        );
        if let Ok(false) = ok {
            process::exit(1)
        }
        process::exit(0);
    }
    for file in files.unwrap() {
        let pb = PathBuf::from(file);
        if let Ok(false) = visit_ucg_files(&pb, recurse, false, strict, cache.clone(), &registry) {
            ok = false;
        }
    }
    if !ok {
        process::exit(1)
    }
}

fn test_command(
    matches: &clap::ArgMatches,
    cache: Rc<RefCell<Cache>>,
    registry: &ConverterRegistry,
    strict: bool,
) {
    let files = matches.values_of("INPUT");
    let recurse = matches.is_present("recurse");
    if files.is_none() {
        let curr_dir = std::env::current_dir().unwrap();
        let ok = visit_ucg_files(
            curr_dir.as_path(),
            recurse,
            true,
            strict,
            cache.clone(),
            &registry,
        );
        if let Ok(false) = ok {
            process::exit(1)
        }
    } else {
        let mut ok = true;
        for file in files.unwrap() {
            let pb = PathBuf::from(file);
            //if pb.is_dir() {
            if let Ok(false) = visit_ucg_files(
                pb.as_path(),
                recurse,
                true,
                strict,
                cache.clone(),
                &registry,
            ) {
                ok = false;
            }
        }
        if !ok {
            process::exit(1)
        }
    }
    process::exit(0);
}

fn converters_command(registry: &ConverterRegistry) {
    println!("Available converters:");
    println!("");
    for (name, c) in registry.get_converter_list().iter() {
        println!("- {}", name);
        println!("  Description: {}", c.description());
        println!("  Output Extension: `.{}`", c.file_ext());
        println!("");
    }
}

fn main() {
    let mut app = do_flags();
    let app_matches = app.clone().get_matches();
    let cache: Rc<RefCell<Cache>> = Rc::new(RefCell::new(MemoryCache::new()));
    let registry = ConverterRegistry::make_registry();
    let strict = if app_matches.is_present("nostrict") {
        false
    } else {
        true
    };
    if let Some(matches) = app_matches.subcommand_matches("inspect") {
        inspect_command(matches, cache, &registry, strict);
    } else if let Some(matches) = app_matches.subcommand_matches("build") {
        build_command(matches, cache, &registry, strict);
    } else if let Some(matches) = app_matches.subcommand_matches("test") {
        test_command(matches, cache, &registry, strict);
    } else if let Some(_) = app_matches.subcommand_matches("converters") {
        converters_command(&registry)
    } else {
        app.print_help().unwrap();
        println!("");
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate env_logger;

use std::env;
use std::io::{self, Read};
use std::str;

use rustc_serialize::json;

fn main() {
    env_logger::init();
    let port = get_server_port();
    let _l = hyper::Server::new(handle).listen(("127.0.0.1", port));
    println!("Listening on http://127.0.0.1:{}", port);
}

const DEFAULT_PORT: u16 = 8080;

fn get_server_port() -> u16 {
    match env::var("PORT") {
        Ok(val) => u16::from_str_radix(&val, 10).unwrap_or(DEFAULT_PORT),
        Err(_) => DEFAULT_PORT
    }
}
fn handle(req: hyper::server::Request, mut res: hyper::server::Response<hyper::net::Fresh>) {
    match (req.method, req.uri) {
        (hyper::Get, hyper::uri::RequestUri::AbsolutePath(path)) => {
            let version = match lookup(&path[1..]) {
                Ok(v) => v,
                Err(..) => return not_found(res)
            };
            let badge = format!("https://img.shields.io/badge/crates.io-{}-green.svg", version);
            *res.status_mut() = hyper::status::StatusCode::Found;
            res.headers_mut().set(hyper::header::Location(badge));
            let _ = res.start().and_then(|res| res.end());
        },
        _ => not_found(res)
    };
}

fn not_found(mut res: hyper::server::Response<hyper::net::Fresh>) {
    *res.status_mut() = hyper::NotFound;
    let _ = res.start().and_then(|res| res.end());
}

type LookupResult = Result<String, LookupError>;

enum LookupError {
    NotFound,
    Http(hyper::HttpError),
    Io(io::Error)
}

impl From<hyper::HttpError> for LookupError {
    fn from(e: hyper::HttpError) -> LookupError {
        LookupError::Http(e)
    }
}

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

#[derive(Debug)]
struct LookupCrate {
    version: String
}

impl rustc_serialize::Decodable for LookupCrate {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<LookupCrate, D::Error> {
        Ok(LookupCrate {
            version: try!(d.read_struct("", 1, |d| {
                d.read_struct_field("crate", 1, |d| {
                    d.read_struct("", 1, |d| {
                        d.read_struct_field("max_version", 0, |d| d.read_str())
                    })
                })
            }))
        })
    }
}
fn lookup(krate: &str) -> LookupResult {
    let mut client = hyper::Client::new();
    let url = format!("https://crates.io/api/v1/crates/{}", krate);
    let mut res = try!(client.get(&*url).send());
    if res.status != hyper::Ok {
        return Err(LookupError::NotFound);
    }

    let mut buf = Vec::new();
    try!(res.read_to_end(&mut buf));

    let text = match str::from_utf8(&buf) {
        Ok(text) => text,
        _ => return Err(LookupError::NotFound)
    };

    let map: LookupCrate = match json::decode(text) {
        Ok(map) => map,
        _ => return Err(LookupError::NotFound)
    };

    Ok(map.version)
}
<commit_msg>use env_logger result<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate env_logger;

use std::env;
use std::io::{self, Read};
use std::str;

use rustc_serialize::json;

fn main() {
    env_logger::init().unwrap();
    let listening = hyper::Server::new(handle).listen(("127.0.0.1", get_server_port()));
    println!("Listening on http://{}", listening.socket);
}

const DEFAULT_PORT: u16 = 8080;

fn get_server_port() -> u16 {
    match env::var("PORT") {
        Ok(val) => u16::from_str_radix(&val, 10).unwrap_or(DEFAULT_PORT),
        Err(_) => DEFAULT_PORT
    }
}
fn handle(req: hyper::server::Request, mut res: hyper::server::Response<hyper::net::Fresh>) {
    match (req.method, req.uri) {
        (hyper::Get, hyper::uri::RequestUri::AbsolutePath(path)) => {
            let version = match lookup(&path[1..]) {
                Ok(v) => v,
                Err(..) => return not_found(res)
            };
            let badge = format!("https://img.shields.io/badge/crates.io-{}-green.svg", version);
            *res.status_mut() = hyper::status::StatusCode::Found;
            res.headers_mut().set(hyper::header::Location(badge));
            let _ = res.start().and_then(|res| res.end());
        },
        _ => not_found(res)
    };
}

fn not_found(mut res: hyper::server::Response<hyper::net::Fresh>) {
    *res.status_mut() = hyper::NotFound;
    let _ = res.start().and_then(|res| res.end());
}

type LookupResult = Result<String, LookupError>;

enum LookupError {
    NotFound,
    Http(hyper::HttpError),
    Io(io::Error)
}

impl From<hyper::HttpError> for LookupError {
    fn from(e: hyper::HttpError) -> LookupError {
        LookupError::Http(e)
    }
}

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

#[derive(Debug)]
struct LookupCrate {
    version: String
}

impl rustc_serialize::Decodable for LookupCrate {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<LookupCrate, D::Error> {
        Ok(LookupCrate {
            version: try!(d.read_struct("", 1, |d| {
                d.read_struct_field("crate", 1, |d| {
                    d.read_struct("", 1, |d| {
                        d.read_struct_field("max_version", 0, |d| d.read_str())
                    })
                })
            }))
        })
    }
}
fn lookup(krate: &str) -> LookupResult {
    let mut client = hyper::Client::new();
    let url = format!("https://crates.io/api/v1/crates/{}", krate);
    let mut res = try!(client.get(&*url).send());
    if res.status != hyper::Ok {
        return Err(LookupError::NotFound);
    }

    let mut buf = Vec::new();
    try!(res.read_to_end(&mut buf));

    let text = match str::from_utf8(&buf) {
        Ok(text) => text,
        _ => return Err(LookupError::NotFound)
    };

    let map: LookupCrate = match json::decode(text) {
        Ok(map) => map,
        _ => return Err(LookupError::NotFound)
    };

    Ok(map.version)
}
<|endoftext|>


<commit_before>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;

extern crate ncurses;
use ncurses::*;

//extern crate getopts;
//use getopts::Options;

fn main() {
    let mut buffer = vec![];
    let mut cursorpos:usize = 0;
    let mut cursorstate:usize = 0; //0 is left nibble, 1 is right nibble, 2 is ascii
    const SPALTEN:usize = 16;
    let mut command = String::new();

    initscr(); //start ncursesw
    let screenheight : usize = getmaxy(stdscr) as usize;
    cbreak();  //ctrl+z and fg works with this
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    printw("Welcome to Hexdino.\nPlease find the any-key on your keyboard and press it.\n");

    let args: Vec<_> = env::args().collect();
    /*
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("f", "", "set file name", "NAME");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        let brief = format!("Usage: {} FILE [options]", program);
            print!("{}", opts.usage(&brief));
        return;
    }
    let path = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        let brief = format!("Usage: {} FILE [options]", program);
            print!("{}", opts.usage(&brief));
        return;
    };*/

    let path = if args.len() > 1 {
        printw(&format!("Opening file {}", args[1]));
        args[1].clone()
    } else {
        printw(&format!("No file specified. Trying to open foo.txt"));
        "foo.txt".into()
    };

    let path = Path::new(&path);
    let display = path.display();

    getch();
    clear();

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

//TODO in this order: 1)disp files 2) hjkl movement 3) edit file by 'r' 4) save file 5) edit file by 'x, i' 6) search by '/'

    let mut file = match OpenOptions::new().read(true).write(true).create(true).open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display,
            Error::description(&why)),
        Ok(file) => file,
    };

    file.read_to_end(&mut buffer).ok().expect("File could not be read.");

    let mut mode = 0; // 0 Command mode, 1 replace next char, 2 type a command, TODO 3 Insert

    draw(&buffer, cursorpos, SPALTEN, screenheight, mode, &command, cursorstate);

    let mut key;
//    key = getch();
//    printw(&format!("{:?}", key));

    let mut ragequitnow = 0;
    while ragequitnow == 0 {
        key = getch();
        if mode == 0 { // movement mode
            match key {
                104 => { // Button "h"
                    if cursorstate == 1 { cursorstate = 0;}
                    else if cursorpos != 0 { cursorstate = 1; cursorpos-=1}
                },
                106 => if cursorpos+SPALTEN < buffer.len() {cursorpos+=SPALTEN} //down is "+16"
                        else {cursorpos=buffer.len()-1}, //down if on last line is "to end"
                107 => if cursorpos >= SPALTEN {cursorpos-=SPALTEN}, //up is "-16"
                108 => { // Button "l"
                    if cursorstate == 0 { cursorstate = 1; }
                    else if cursorstate == 1 && cursorpos != buffer.len()-1 { cursorstate = 0; cursorpos+=1; }
                },
                 48 => { // Start of line is "to start"
                     cursorpos -= cursorpos%16;
                     cursorstate = 0;
                },
                 36 => { //dollar is "to end"
                     if cursorpos-(cursorpos%16)+(SPALTEN-1) < buffer.len() {cursorpos = cursorpos-(cursorpos%16)+(SPALTEN-1)}
                        else {cursorpos = buffer.len()-1};
                    cursorstate = 1;
                },
                114 => mode = 1, //r replaces the next char
                 58 => {mode = 2; // ":"
                            command.clear();},
//                 63 => printw("{:?}", asdf), //TODO: print available key helpfile
                _ => (),
            }
        } else
        if mode == 1 && cursorstate == 2 { // r was pressed so replace next char in ascii mode
            match key {
                c @ 32...126 => { buffer[cursorpos] = c as u8 },
                _ => (),
            }
            mode = 0;
        } else
        if mode == 1 && cursorstate == 0 {
            match key { // Change left nibble
                c @  65... 70 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 55)<<4 }, //A-F
                c @  97...102 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 55)<<4 }, //a-f
                c @  48... 57 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 48)<<4 }, //0-9
                _ => ()
            }
            mode = 0;
        } else
        if mode == 1 && cursorstate == 1 {
            match key { // Chnage right nibble
                c @  65... 70 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 55)<<0 }, //A-F
                c @  97...102 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 55)<<0 }, //a-f
                c @  48... 57 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 48)<<0 }, //0-9
                _ => ()
            }
            mode = 0;
        } else
        if mode == 2 {
            match key {
                c @ 32...126 => { command.push(c as u8 as char); }, //TODO check this
                27 => {command.clear();mode = 0;},
                10 => { // Enter pressed, compute command!
                        if (command == "w".to_string()) || (command == "wq".to_string()) {
                            file.seek(SeekFrom::Start(0)).ok().expect("Filepointer could not be set to 0");
                            file.write_all(&mut buffer).ok().expect("File could not be written.");
                            if command == "wq".to_string() {
                                ragequitnow = 1;
                            }
                            command.clear();mode = 0;
                        }
                        else if command == "q".to_string() {
                            ragequitnow = 1;
                        }
                        else {
                            command.clear();
                            command.push_str("Bad_command!");
                            mode = 0;
                        }
                    },
                _ => (),
            }
        }
        draw(&buffer, cursorpos, SPALTEN, screenheight, mode, &command, cursorstate);
    }

    refresh();
    endwin();
}

fn draw(buffer:&Vec<u8>, cursorpos:usize, spalten:usize, maxzeilen:usize, mode:usize, command:&String, cursorstate:usize) {
//    let zeilen = buffer.len() / spalten;
    erase();

    let mut zeilen = buffer.len() / spalten;
    if zeilen >= maxzeilen-1 { // Last line reserved for Status/Commands/etc (Like in vim)
        zeilen = maxzeilen-2;
    }

    for z in 0 .. zeilen+1 {
        printw(&format!("{:08X}: ", z * spalten )); // 8 hex digits (4GB/spalten or 0.25GB@spalten=16)
        printw(" "); // Additional space between line number and hex
        for s in 0 .. spalten {
            if z*spalten+s < buffer.len() {
                if z*spalten+s == cursorpos && cursorstate == 0 { attron(COLOR_PAIR(1)); } // Color of left nibble
                printw(&format!("{:01X}", buffer[z*spalten+s]>>4) ); // Display left nibble
                if z*spalten+s == cursorpos && cursorstate == 0 { attroff(COLOR_PAIR(1)); }

                if z*spalten+s == cursorpos && cursorstate == 1 { attron(COLOR_PAIR(1)); } // Color of right nibble
                printw(&format!("{:01X} ", buffer[z*spalten+s]&0x0F) ); // Display right nibble
                if z*spalten+s == cursorpos && cursorstate == 1 { attroff(COLOR_PAIR(1)); }
            } else {
                printw("-- ");
            }
        }
        printw(" "); // Additional space between hex and ascii
        for s in 0 .. spalten {
            if z*spalten+s == cursorpos && cursorstate == 2 { attron(COLOR_PAIR(1)); }
                if z*spalten+s < buffer.len() {
                    if let c @ 32...126 = buffer[z*spalten+s] {
                        if c as char == '%' {
                            printw("%%"); // '%' needs to be escaped by a '%' in ncurses
                        } else {
                            printw(&format!("{}", c as char) );
                        }
                    }
                    else {printw(&format!(".") );}
                }
            if z*spalten+s == cursorpos && cursorstate == 2 { attroff(COLOR_PAIR(1)); }
        }
        printw("\n");
    }
    for _ in 0 .. maxzeilen-zeilen-2 {
        printw("\n"); // Put the cursor on last line of terminal
    }
    if mode == 2 {
        printw(":"); // Indicate that a command can be typed in
    }
    printw(&format!("{}", command));
}
<commit_msg>Add ability to remove/insert bytes<commit_after>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;

extern crate ncurses;
use ncurses::*;

//extern crate getopts;
//use getopts::Options;

fn main() {
    let mut buffer = vec![];
    let mut cursorpos:usize = 0;
    let mut cursorstate:usize = 0; //0 is left nibble, 1 is right nibble, 2 is ascii
    const SPALTEN:usize = 16;
    let mut command = String::new();

    initscr(); //start ncursesw
    let screenheight : usize = getmaxy(stdscr) as usize;
    cbreak();  //ctrl+z and fg works with this
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    printw("Welcome to Hexdino.\nPlease find the any-key on your keyboard and press it.\n");

    let args: Vec<_> = env::args().collect();
    /*
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("f", "", "set file name", "NAME");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        let brief = format!("Usage: {} FILE [options]", program);
            print!("{}", opts.usage(&brief));
        return;
    }
    let path = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        let brief = format!("Usage: {} FILE [options]", program);
            print!("{}", opts.usage(&brief));
        return;
    };*/

    let path = if args.len() > 1 {
        printw(&format!("Opening file {}", args[1]));
        args[1].clone()
    } else {
        printw(&format!("No file specified. Trying to open foo.txt"));
        "foo.txt".into()
    };

    let path = Path::new(&path);
    let display = path.display();

    getch();
    clear();

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

//TODO in this order: 1)disp files 2) hjkl movement 3) edit file by 'r' 4) save file 5) edit file by 'x, i' 6) search by '/'

    let mut file = match OpenOptions::new().read(true).write(true).create(true).open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display,
            Error::description(&why)),
        Ok(file) => file,
    };

    file.read_to_end(&mut buffer).ok().expect("File could not be read.");

    let mut mode = 0; // 0 Command mode, 1 replace next char, 2 type a command, TODO 3 Insert

    draw(&buffer, cursorpos, SPALTEN, screenheight, mode, &command, cursorstate);

    let mut key;
//    key = getch();
//    printw(&format!("{:?}", key));

    let mut ragequitnow = 0;
    while ragequitnow == 0 {
        key = getch();
        if mode == 0 { // movement mode
            match key {
                104 => { // Button "h"
                    if cursorstate == 1 { cursorstate = 0;}
                    else if cursorpos != 0 { cursorstate = 1; cursorpos-=1}
                },
                106 => if cursorpos+SPALTEN < buffer.len() {cursorpos+=SPALTEN} //down is "+16"
                        else {cursorpos=buffer.len()-1}, //down if on last line is "to end"
                107 => if cursorpos >= SPALTEN {cursorpos-=SPALTEN}, //up is "-16"
                108 => { // Button "l"
                    if cursorstate == 0 { cursorstate = 1; }
                    else if cursorstate == 1 && cursorpos != buffer.len()-1 { cursorstate = 0; cursorpos+=1; }
                },
                 48 => { // Start of line is "to start"
                     cursorpos -= cursorpos%16;
                     cursorstate = 0;
                },
                 36 => { //dollar is "to end"
                     if cursorpos-(cursorpos%16)+(SPALTEN-1) < buffer.len() {cursorpos = cursorpos-(cursorpos%16)+(SPALTEN-1)}
                        else {cursorpos = buffer.len()-1};
                    cursorstate = 1;
                },
                114 => mode = 1, //r replaces the next char
                120 => {buffer.remove(cursorpos);}, //x remove the next char
                105 => {buffer.insert(cursorpos, 0x00);},
                 58 => {mode = 2; // ":"
                            command.clear();},
//                 63 => printw("{:?}", asdf), //TODO: print available key helpfile
                _ => (),
            }
        } else
        if mode == 1 && cursorstate == 2 { // r was pressed so replace next char in ascii mode
            match key {
                c @ 32...126 => { buffer[cursorpos] = c as u8 },
                _ => (),
            }
            mode = 0;
        } else
        if mode == 1 && cursorstate == 0 {
            match key { // Change left nibble
                c @  65... 70 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 55)<<4 }, //A-F
                c @  97...102 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 55)<<4 }, //a-f
                c @  48... 57 => { buffer[cursorpos] = buffer[cursorpos]&0x0F | (c as u8 - 48)<<4 }, //0-9
                _ => ()
            }
            mode = 0;
        } else
        if mode == 1 && cursorstate == 1 {
            match key { // Chnage right nibble
                c @  65... 70 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 55)<<0 }, //A-F
                c @  97...102 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 55)<<0 }, //a-f
                c @  48... 57 => { buffer[cursorpos] = buffer[cursorpos]&0xF0 | (c as u8 - 48)<<0 }, //0-9
                _ => ()
            }
            mode = 0;
        } else
        if mode == 2 {
            match key {
                c @ 32...126 => { command.push(c as u8 as char); }, //TODO check this
                27 => {command.clear();mode = 0;},
                10 => { // Enter pressed, compute command!
                        if (command == "w".to_string()) || (command == "wq".to_string()) {
                            file.seek(SeekFrom::Start(0)).ok().expect("Filepointer could not be set to 0");
                            file.write_all(&mut buffer).ok().expect("File could not be written.");
                            if command == "wq".to_string() {
                                ragequitnow = 1;
                            }
                            command.clear();mode = 0;
                        }
                        else if command == "q".to_string() {
                            ragequitnow = 1;
                        }
                        else {
                            command.clear();
                            command.push_str("Bad_command!");
                            mode = 0;
                        }
                    },
                _ => (),
            }
        }
        draw(&buffer, cursorpos, SPALTEN, screenheight, mode, &command, cursorstate);
    }

    refresh();
    endwin();
}

fn draw(buffer:&Vec<u8>, cursorpos:usize, spalten:usize, maxzeilen:usize, mode:usize, command:&String, cursorstate:usize) {
//    let zeilen = buffer.len() / spalten;
    erase();

    let mut zeilen = buffer.len() / spalten;
    if zeilen >= maxzeilen-1 { // Last line reserved for Status/Commands/etc (Like in vim)
        zeilen = maxzeilen-2;
    }

    for z in 0 .. zeilen+1 {
        printw(&format!("{:08X}: ", z * spalten )); // 8 hex digits (4GB/spalten or 0.25GB@spalten=16)
        printw(" "); // Additional space between line number and hex
        for s in 0 .. spalten {
            if z*spalten+s < buffer.len() {
                if z*spalten+s == cursorpos && cursorstate == 0 { attron(COLOR_PAIR(1)); } // Color of left nibble
                printw(&format!("{:01X}", buffer[z*spalten+s]>>4) ); // Display left nibble
                if z*spalten+s == cursorpos && cursorstate == 0 { attroff(COLOR_PAIR(1)); }

                if z*spalten+s == cursorpos && cursorstate == 1 { attron(COLOR_PAIR(1)); } // Color of right nibble
                printw(&format!("{:01X} ", buffer[z*spalten+s]&0x0F) ); // Display right nibble
                if z*spalten+s == cursorpos && cursorstate == 1 { attroff(COLOR_PAIR(1)); }
            } else {
                printw("-- ");
            }
        }
        printw(" "); // Additional space between hex and ascii
        for s in 0 .. spalten {
            if z*spalten+s == cursorpos && cursorstate == 2 { attron(COLOR_PAIR(1)); }
                if z*spalten+s < buffer.len() {
                    if let c @ 32...126 = buffer[z*spalten+s] {
                        if c as char == '%' {
                            printw("%%"); // '%' needs to be escaped by a '%' in ncurses
                        } else {
                            printw(&format!("{}", c as char) );
                        }
                    }
                    else {printw(&format!(".") );}
                }
            if z*spalten+s == cursorpos && cursorstate == 2 { attroff(COLOR_PAIR(1)); }
        }
        printw("\n");
    }
    for _ in 0 .. maxzeilen-zeilen-2 {
        printw("\n"); // Put the cursor on last line of terminal
    }
    if mode == 2 {
        printw(":"); // Indicate that a command can be typed in
    }
    printw(&format!("{}", command));
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// FIXME Remove before 1.0
#![feature(ip_addr)]

/// This example shows a basic packet logger using libpnet

extern crate pnet;

use std::env;
use std::net::{IpAddr};

use pnet::packet::{Packet};
use pnet::packet::ethernet::{EthernetPacket, EtherTypes};
use pnet::packet::ip::{IpNextHeaderProtocol, IpNextHeaderProtocols};
use pnet::packet::ipv4::{Ipv4Packet};
use pnet::packet::ipv6::{Ipv6Packet};
use pnet::packet::udp::{UdpPacket};

use pnet::datalink::{datalink_channel};
use pnet::datalink::DataLinkChannelType::{Layer2};

use pnet::util::{NetworkInterface, get_network_interfaces};

fn handle_udp_packet(interface_name: &str, source: IpAddr, destination: IpAddr, packet: &[u8]) {
    let udp = UdpPacket::new(packet);

    if let Some(udp) = udp {
        println!("[{}]: UDP Packet: {}:{} > {}:{}; length: {}", interface_name, source,
                        udp.get_source(), destination, udp.get_destination(), udp.get_length());
    } else {
        println!("[{}]: Malformed UDP Packet", interface_name);
    }
}

fn handle_tcp_packet(interface_name: &str, source: IpAddr, destination: IpAddr, packet: &[u8]) {
    // Since we only look at source and destination ports, and these are located in the same
    // place in both TCP and UDP headers, we cheat here
    let udp = UdpPacket::new(packet);
    if let Some(udp) = udp {
        println!("[{}]: TCP Packet: {}:{} > {}:{}; length: {}", interface_name, source,
                    udp.get_source(), destination, udp.get_destination(), packet.len());
    } else {
        println!("[{}]: Malformed TCP Packet", interface_name);
    }
}

fn handle_transport_protocol(interface_name: &str, source: IpAddr, destination: IpAddr,
                             protocol: IpNextHeaderProtocol, packet: &[u8]) {
    match protocol {
        IpNextHeaderProtocols::Udp  => handle_udp_packet(interface_name, source, destination, packet),
        IpNextHeaderProtocols::Tcp  => handle_tcp_packet(interface_name, source, destination, packet),
        _ => println!("[{}]: Unknown {} packet: {} > {}; protocol: {:?} length: {}",
                interface_name,
                match source { IpAddr::V4(..) => "IPv4", _ => "IPv6" },
                source,
                destination,
                protocol,
                packet.len())

    }
}

fn handle_ipv4_packet(interface_name: &str, ethernet: &EthernetPacket) {
    let header = Ipv4Packet::new(ethernet.payload());
    if let Some(header) = header {
        handle_transport_protocol(interface_name,
                                  IpAddr::V4(header.get_source()),
                                  IpAddr::V4(header.get_destination()),
                                  header.get_next_level_protocol(),
                                  header.payload());
    } else {
        println!("[{}]: Malformed IPv4 Packet", interface_name);
    }
}

fn handle_ipv6_packet(interface_name: &str, ethernet: &EthernetPacket) {
    let header = Ipv6Packet::new(ethernet.payload());
    if let Some(header) = header {
        handle_transport_protocol(interface_name,
                                  IpAddr::V6(header.get_source()),
                                  IpAddr::V6(header.get_destination()),
                                  header.get_next_header(),
                                  header.payload());
    } else {
        println!("[{}]: Malformed IPv6 Packet", interface_name);
    }
}

fn handle_arp_packet(interface_name: &str, ethernet: &EthernetPacket) {
    println!("[{}]: ARP packet: {} > {}; length: {}",
            interface_name,
            ethernet.get_source(),
            ethernet.get_destination(),
            ethernet.packet().len())

}

fn handle_packet(interface_name: &str, ethernet: &EthernetPacket) {
    match ethernet.get_ethertype() {
        EtherTypes::Ipv4 => handle_ipv4_packet(interface_name, ethernet),
        EtherTypes::Ipv6 => handle_ipv6_packet(interface_name, ethernet),
        EtherTypes::Arp  => handle_arp_packet(interface_name, ethernet),
        _                => println!("[{}]: Unknown packet: {} > {}; ethertype: {:?} length: {}",
                                        interface_name,
                                        ethernet.get_source(),
                                        ethernet.get_destination(),
                                        ethernet.get_ethertype(),
                                        ethernet.packet().len())
    }
}

fn main() {
    let iface_name = env::args().nth(1).unwrap();
    let interface_names_match = |iface: &NetworkInterface| iface.name == iface_name;

    // Find the network interface with the provided name
    let interfaces = get_network_interfaces();
    let interface = interfaces.into_iter()
                              .filter(interface_names_match)
                              .next()
                              .unwrap();

    // Create a channel to receive on
    let (_, mut rx) = match datalink_channel(&interface, 0, 4096, Layer2) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("packetdump: unable to create channel: {}", e)
    };

    let mut iter = rx.iter();
    loop {
        match iter.next() {
            Ok(packet) => handle_packet(&interface.name[..], &packet),
            Err(e) => panic!("packetdump: unable to receive packet: {}", e)
        }
    }
}
<commit_msg>collecting arp results<commit_after>extern crate pnet;

use std::env;

use pnet::packet::{Packet};
use pnet::packet::ethernet::{EthernetPacket, EtherTypes};

use pnet::datalink::{datalink_channel};
use pnet::datalink::DataLinkChannelType::{Layer2};

use pnet::util::{NetworkInterface, get_network_interfaces};

fn handle_arp_packet(interface_name: &str, ethernet: &EthernetPacket) {
    if ethernet.packet()[21] == 1 { return }

    println!("[{}]: ARP packet: {} > {}; length: {}; data: {:?}",
            interface_name,
            ethernet.get_source(),
            ethernet.get_destination(),
            ethernet.packet().len(),
            ethernet.packet());

    println!("{}.{}.{}.{}",
            ethernet.packet()[38],
            ethernet.packet()[39],
            ethernet.packet()[40],
            ethernet.packet()[41])
}

fn handle_packet(interface_name: &str, ethernet: &EthernetPacket) {
    match ethernet.get_ethertype() {
        EtherTypes::Arp  => handle_arp_packet(interface_name, ethernet),
        _ => return,
    }
}

fn main() {
    let iface_name = env::args().nth(1).unwrap();
    let interface_names_match = |iface: &NetworkInterface| iface.name == iface_name;

    // Find the network interface with the provided name
    let interfaces = get_network_interfaces();
    let interface = interfaces.into_iter()
                              .filter(interface_names_match)
                              .next()
                              .unwrap();

    // Create a channel to receive on
    let (_, mut rx) = match datalink_channel(&interface, 0, 4096, Layer2) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("packetdump: unable to create channel: {}", e)
    };

    let mut iter = rx.iter();
    loop {
        match iter.next() {
            Ok(packet) => handle_packet(&interface.name[..], &packet),
            Err(e) => panic!("packetdump: unable to receive packet: {}", e)
        }
    }
}
<|endoftext|>