<commit_before>// rust version of breakfast tool
// BreakFast is a toolkit for detecting chromosomal rearrangements
// based on RNA-seq data.

use std::env;
use std::mem;
use std::path::Path;
use std::io::prelude::*;
use std::fs;
use std::fs::File;
use std::process::{Command, Stdio};
use std::collections::HashMap;
use std::io::{BufReader, BufRead, Read, Write};
use rust_htslib::bam;
use rust_htslib::bam::Read as HTSRead;

extern crate clap;
extern crate bio;
extern crate rust_htslib;

mod cli;
mod lib;

// struct for having breakfast options
struct BfOptions {
    anchor_len :    usize,
    max_frag_len:   i32,
    min_mapq:       i32,
    orientation:    &'static str,
    all_reads:      bool,
    discard_duplicates: &'static str,
    min_reads:      &'static str,
    freq_above:     i32,
}

struct Evidence {
	chr: String,
	pos: u32,
	strand: bool,
	mchr: String,
	mpos: u32,
	mstrand: bool,
	sequence: String,
	frag_id: String,
	signature: String     // Breakpoint signature
}

fn main() {
  let defaults = BfOptions{ anchor_len : 0,
                            max_frag_len: 5000,
                            min_mapq: 15,
                            orientation:  "fr",
                            all_reads:  false,
                            discard_duplicates: "both-ends",
                            min_reads:    "0-0-0",
                            freq_above: 0};

  let mut anchor_len: usize   = defaults.anchor_len;
  let mut max_frag_len: i32 = defaults.max_frag_len;
  let mut min_mapq: i32     = defaults.min_mapq;
  let mut orientation       = String::from(defaults.orientation);
  let mut all_reads: bool   = defaults.all_reads;
  let mut discard_duplicates = String::from(defaults.discard_duplicates);
  let mut min_reads     = String::from(defaults.min_reads);
  let mut freq_above: i32 = defaults.freq_above;

  //arguments from src/cli.rs
  let matches = cli::build_cli().get_matches();
  //arguments from detect subcommand
  if let ("detect", Some(detect)) = matches.subcommand() {
      let bam_file = String::from(detect.value_of("bam_file").unwrap());
      let genome   = String::from(detect.value_of("genome").unwrap());
      let out_prefix  = String::from(detect.value_of("out_prefix").unwrap());

      if detect.is_present("anchor-len") {
          anchor_len = detect.value_of("anchor-len").unwrap().parse().unwrap();
      }

      if detect.is_present("orientation") {
          orientation = String::from(detect.value_of("orientation").unwrap());
      }
      //detect_discordant_pairs(bam_file, out_prefix, max_frag_len, min_mapq, orientation);
      detect_discordant_reads(bam_file, genome, out_prefix, anchor_len);
  }

  //arguments from detectspecific subcommand
  if let ("detectspecific", Some(detectspecific)) = matches.subcommand() {
      let bam_file = String::from(detectspecific.value_of("bam_file").unwrap());
      let genome   = String::from(detectspecific.value_of("genome").unwrap());
      let out_prefix  = String::from(detectspecific.value_of("out_prefix").unwrap());
      let donors  = String::from(detectspecific.value_of("donors").unwrap());
      let acceptors  = String::from(detectspecific.value_of("acceptors").unwrap());
  }

  println!("Hello, world!");
}

// DETECT //
//======= //

// fn detect_discordant_pairs(sam_path: String, out_prefix: String, max_frag_len: i32,
// 	min_mapq: i32, orientation: String) {
//   println!("{:?}\t{:?}\t{:?}\t{:?}\t{:?}", sam_path, out_prefix, max_frag_len, min_mapq, orientation);

//   let mut N = 0;
//   let tmp = out_prefix.clone();
//   let given_path = Path::new(&tmp);
//   let mut sort_tmp_dir = Path::new("./");
//   if given_path.is_absolute()  {
//         sort_tmp_dir = given_path.parent().unwrap();
//   }

//   let extn = String::from(".discordant_pairs.tsv.gz");
//   let out  = out_prefix + &extn;
//   let mut file = File::create("test.txt").unwrap();

//   lib::mkdir(&tmp);
//   println!("Searching for discordant read pairs ...");

//   let (code, stdout, stderr) = sh!("sam discordant pairs --min-mapq={} {} {} | sort -k1,1 -T {:?}", min_mapq, sam_path, max_frag_len, sort_tmp_dir);

//   let mut prev : Vec<&str> = Vec::new();
//   for line in stdout.lines() {
//       let mut cols: Vec<&str> = line.split('\t').collect();
//       if cols.len() < 9 { continue; }

//       //let r1 = Regex::new(r"N").unwrap();
//       //let r2 = Regex::new(r"S").unwrap();

//       if r1.is_match(cols[5]) || r2.is_match(cols[5]) { continue; }
//       else if cols[0].ends_with("/1") || cols[0].ends_with("/2") {
//           let tmp : Vec<&str> = cols[0].split('/').collect();
//           cols[0] = tmp[0];
//       }
//       if prev.len() <= 0 { prev = cols.clone(); }
//       else if prev.len() > 0 && cols[0] != prev[0] { prev = cols.clone(); }

//       let flags = &cols[1].parse::<i32>().unwrap();
//       let mut chr   = String::from(cols[2]);
//       let mut mchr  = String::from(prev[2]);
//       let mut strand = '-';
//       let mut mstrand = '-';
//       let mut pos  = cols[3].parse::<i32>().unwrap();
//       let mut mpos = prev[3].parse::<i32>().unwrap();
//       let mut rlen = cols[9].clone().len() as i32;
//       let mut mrlen= prev[9].clone().len() as i32;

//       if chr.starts_with("chr") {  chr = chr; }
//       else { let prefix = String::from("chr"); chr = prefix + &chr;}

//       if mchr.starts_with("chr") {  chr = chr ;}
//       else { let prefix = String::from("chr"); mchr = prefix + &mchr;}

//       if chr.contains("chrM") || mchr.contains("chrM") { continue;}

//       if orientation == "fr" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);
//           mem::swap(&mut strand, &mut mstrand);
//         }
//         if mstrand == '+' { mstrand = '-';}
//         else { mstrand = '+'; }
//       }

//       else if orientation == "rf" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);
//           mem::swap(&mut strand, &mut mstrand);
//         }
//         if strand == '+' { strand = '-';}
//         else { strand = '+'; }
//       }

//       else if orientation == "ff" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);

//           if mstrand == '-' { mstrand = '+';} else { mstrand = '-'; }
//           if strand  == '-' { strand  = '+';} else { strand  = '-'; }
//           mem::swap(&mut strand, &mut mstrand);
//         }
//       } else { panic!("Unsupported read orientation detected."); }

//       if strand  == '-' { pos  +=  rlen - 1;}
//       if mstrand == '-' { mpos += mrlen - 1;}

//       let mut out = String::new();
//       out.push_str(&chr);out.push_str(&"\t");
//       out.push_str(&strand.to_string());out.push_str(&"\t");
//       out.push_str(&pos.to_string());out.push_str(&"\t");
//       out.push_str(&mchr);out.push_str(&"\t");
//       out.push_str(&mstrand.to_string());out.push_str(&"\t");
//       out.push_str(&mpos.to_string());out.push_str(&"\t-\n");
//       file.write_all(out.as_bytes());
//       N += 1;
//     }
//     let (wcode, wstdout, wstderr) = sh!("gzip -c {:?}.txt > {}", given_path, out);
//     let mut rm_tmp = tmp.to_string() + ".txt";
//     fs::remove_file(rm_tmp);
//     println!("Found {:?} discordant mate pairs.", N);
// }

fn detect_discordant_reads(sam_path: String, genome_path: String, out_prefix: String, anchor_len: usize) {

    println!("Splitting unaligned reads into {} bp anchors and aligning against the genome...", anchor_len);

    println!("{:?}\t{:?}\t{:?}\t", &sam_path, &anchor_len, &genome_path);

    println!("Reading reference genome into memory...");
	let fastq = bio::io::fasta::Reader::from_file("/home/annalam/homo_sapiens/hg38.fa").unwrap();
	let mut genome = HashMap::new();
	for entry in fastq.records() {
		let chr = entry.unwrap();
		genome.insert(chr.id().unwrap().to_owned(), chr.seq().to_owned());
	}

    let mut bowtie = Command::new("bowtie")
		.args(&["-f", "-p1", "-v0", "-m1", "-B1", "--suppress", "5,6,7,8", &genome_path, "-"])
        .stdin(Stdio::piped()).stdout(Stdio::piped())
        .spawn().unwrap();
    let mut bowtie_stdin = bowtie.stdin.as_mut().unwrap();

	let bam = bam::Reader::from_path(&sam_path).unwrap();
	let mut R = 0;
	for r in bam.records() {
		let read = r.unwrap();
		if read.is_unmapped() == false { continue; }
		if read.seq().len() < anchor_len * 2 { continue; }
		// TODO: Extract anchors from both ends of read and write in
		// interleaved FASTA format to the stdin of Bowtie.
		R += 1;
		write!(bowtie_stdin, ">{}_1\n{:?}\n", R, &read.seq().as_bytes()[..anchor_len]);
	}

    /*
    if let Some(ref mut stdout)  = sam.stdout {
      if let Some(ref mut stdin) = fas.stdin {
          let mut buf: Vec<u8> = Vec::new();
          stdout.read_to_end(&mut buf).unwrap();
          stdin.write_all(&buf).unwrap();
          }
        }
    let res = fas.wait_with_output().unwrap().stdout;
    */
    // let mut samres = String::new();
    //   match sam.stdout.unwrap().read_to_string(&mut samres) {
    //       Err(why) => panic!("samtools not running!"),
    //       Ok(_) => print!("samtools worked!"),
    //   }

    // match fas.stdin.unwrap().write_all(samres.as_bytes()) {
    //     Err(why) => panic!("samtools results not reaching fasta"),
    //     Ok(_) => print!("fasta recvied input from samtools"),
    // }

    // let mut res = String::new();
    //   match fas.stdout.unwrap().read_to_string(&mut res) {
    //       Err(why) => panic!("fasta not running!"),
    //       Ok(_) => print!("fasta subcommand worked!"),
    //   }
    //   println!("{:?}", res.len());
}
<commit_msg>new thread for bam reads<commit_after>// rust version of breakfast tool
// BreakFast is a toolkit for detecting chromosomal rearrangements
// based on RNA-seq data.

use std::env;
use std::mem;
use std::thread;
use std::sync::mpsc;
use std::path::Path;
use std::io::prelude::*;
use std::fs;
use std::fs::File;
use std::process::{Command, Stdio};
use std::collections::HashMap;
use std::io::{BufReader, BufRead, Read, Write};
use rust_htslib::bam;
use rust_htslib::bam::Read as HTSRead;

extern crate clap;
extern crate bio;
extern crate rust_htslib;

mod cli;
mod lib;

// struct for having breakfast options
struct BfOptions {
    anchor_len :    usize,
    max_frag_len:   i32,
    min_mapq:       i32,
    orientation:    &'static str,
    all_reads:      bool,
    discard_duplicates: &'static str,
    min_reads:      &'static str,
    freq_above:     i32,
}

struct Evidence {
	chr: String,
	pos: u32,
	strand: bool,
	mchr: String,
	mpos: u32,
	mstrand: bool,
	sequence: String,
	frag_id: String,
	signature: String     // Breakpoint signature
}

fn main() {
  let defaults = BfOptions{ anchor_len : 0,
                            max_frag_len: 5000,
                            min_mapq: 15,
                            orientation:  "fr",
                            all_reads:  false,
                            discard_duplicates: "both-ends",
                            min_reads:    "0-0-0",
                            freq_above: 0};

  let mut anchor_len: usize   = defaults.anchor_len;
  let mut max_frag_len: i32 = defaults.max_frag_len;
  let mut min_mapq: i32     = defaults.min_mapq;
  let mut orientation       = String::from(defaults.orientation);
  let mut all_reads: bool   = defaults.all_reads;
  let mut discard_duplicates = String::from(defaults.discard_duplicates);
  let mut min_reads     = String::from(defaults.min_reads);
  let mut freq_above: i32 = defaults.freq_above;

  //arguments from src/cli.rs
  let matches = cli::build_cli().get_matches();
  //arguments from detect subcommand
  if let ("detect", Some(detect)) = matches.subcommand() {
      let bam_file = String::from(detect.value_of("bam_file").unwrap());
      let genome   = String::from(detect.value_of("genome").unwrap());
      let out_prefix  = String::from(detect.value_of("out_prefix").unwrap());

      if detect.is_present("anchor-len") {
          anchor_len = detect.value_of("anchor-len").unwrap().parse().unwrap();
      }

      if detect.is_present("orientation") {
          orientation = String::from(detect.value_of("orientation").unwrap());
      }
      //detect_discordant_pairs(bam_file, out_prefix, max_frag_len, min_mapq, orientation);
      detect_discordant_reads(bam_file, genome, out_prefix, anchor_len);
  }

  //arguments from detectspecific subcommand
  if let ("detectspecific", Some(detectspecific)) = matches.subcommand() {
      let bam_file = String::from(detectspecific.value_of("bam_file").unwrap());
      let genome   = String::from(detectspecific.value_of("genome").unwrap());
      let out_prefix  = String::from(detectspecific.value_of("out_prefix").unwrap());
      let donors  = String::from(detectspecific.value_of("donors").unwrap());
      let acceptors  = String::from(detectspecific.value_of("acceptors").unwrap());
  }

  println!("Hello, world!");
}

// DETECT //
//======= //

// fn detect_discordant_pairs(sam_path: String, out_prefix: String, max_frag_len: i32,
// 	min_mapq: i32, orientation: String) {
//   println!("{:?}\t{:?}\t{:?}\t{:?}\t{:?}", sam_path, out_prefix, max_frag_len, min_mapq, orientation);

//   let mut N = 0;
//   let tmp = out_prefix.clone();
//   let given_path = Path::new(&tmp);
//   let mut sort_tmp_dir = Path::new("./");
//   if given_path.is_absolute()  {
//         sort_tmp_dir = given_path.parent().unwrap();
//   }

//   let extn = String::from(".discordant_pairs.tsv.gz");
//   let out  = out_prefix + &extn;
//   let mut file = File::create("test.txt").unwrap();

//   lib::mkdir(&tmp);
//   println!("Searching for discordant read pairs ...");

//   let (code, stdout, stderr) = sh!("sam discordant pairs --min-mapq={} {} {} | sort -k1,1 -T {:?}", min_mapq, sam_path, max_frag_len, sort_tmp_dir);

//   let mut prev : Vec<&str> = Vec::new();
//   for line in stdout.lines() {
//       let mut cols: Vec<&str> = line.split('\t').collect();
//       if cols.len() < 9 { continue; }

//       //let r1 = Regex::new(r"N").unwrap();
//       //let r2 = Regex::new(r"S").unwrap();

//       if r1.is_match(cols[5]) || r2.is_match(cols[5]) { continue; }
//       else if cols[0].ends_with("/1") || cols[0].ends_with("/2") {
//           let tmp : Vec<&str> = cols[0].split('/').collect();
//           cols[0] = tmp[0];
//       }
//       if prev.len() <= 0 { prev = cols.clone(); }
//       else if prev.len() > 0 && cols[0] != prev[0] { prev = cols.clone(); }

//       let flags = &cols[1].parse::<i32>().unwrap();
//       let mut chr   = String::from(cols[2]);
//       let mut mchr  = String::from(prev[2]);
//       let mut strand = '-';
//       let mut mstrand = '-';
//       let mut pos  = cols[3].parse::<i32>().unwrap();
//       let mut mpos = prev[3].parse::<i32>().unwrap();
//       let mut rlen = cols[9].clone().len() as i32;
//       let mut mrlen= prev[9].clone().len() as i32;

//       if chr.starts_with("chr") {  chr = chr; }
//       else { let prefix = String::from("chr"); chr = prefix + &chr;}

//       if mchr.starts_with("chr") {  chr = chr ;}
//       else { let prefix = String::from("chr"); mchr = prefix + &mchr;}

//       if chr.contains("chrM") || mchr.contains("chrM") { continue;}

//       if orientation == "fr" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);
//           mem::swap(&mut strand, &mut mstrand);
//         }
//         if mstrand == '+' { mstrand = '-';}
//         else { mstrand = '+'; }
//       }

//       else if orientation == "rf" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);
//           mem::swap(&mut strand, &mut mstrand);
//         }
//         if strand == '+' { strand = '-';}
//         else { strand = '+'; }
//       }

//       else if orientation == "ff" {
//         if chr > mchr || (chr == mchr && pos > mpos) {
//           mem::swap(&mut chr, &mut mchr);
//           mem::swap(&mut pos, &mut mpos);
//           mem::swap(&mut rlen, &mut mrlen);

//           if mstrand == '-' { mstrand = '+';} else { mstrand = '-'; }
//           if strand  == '-' { strand  = '+';} else { strand  = '-'; }
//           mem::swap(&mut strand, &mut mstrand);
//         }
//       } else { panic!("Unsupported read orientation detected."); }

//       if strand  == '-' { pos  +=  rlen - 1;}
//       if mstrand == '-' { mpos += mrlen - 1;}

//       let mut out = String::new();
//       out.push_str(&chr);out.push_str(&"\t");
//       out.push_str(&strand.to_string());out.push_str(&"\t");
//       out.push_str(&pos.to_string());out.push_str(&"\t");
//       out.push_str(&mchr);out.push_str(&"\t");
//       out.push_str(&mstrand.to_string());out.push_str(&"\t");
//       out.push_str(&mpos.to_string());out.push_str(&"\t-\n");
//       file.write_all(out.as_bytes());
//       N += 1;
//     }
//     let (wcode, wstdout, wstderr) = sh!("gzip -c {:?}.txt > {}", given_path, out);
//     let mut rm_tmp = tmp.to_string() + ".txt";
//     fs::remove_file(rm_tmp);
//     println!("Found {:?} discordant mate pairs.", N);
// }

fn detect_discordant_reads(sam_path: String, genome_path: String, out_prefix: String, anchor_len: usize) {

    println!("Splitting unaligned reads into {} bp anchors and aligning against the genome...", anchor_len);

    println!("{:?}\t{:?}\t{:?}\t", &sam_path, &anchor_len, &genome_path);

    println!("Reading reference genome into memory...");
	//let fastq = bio::io::fasta::Reader::from_file("/home/annalam/homo_sapiens/hg38.fa").unwrap();
	let fastq = bio::io::fasta::Reader::from_file("/home/gnanavel/tools/homo_sapiens/hg38.fa").unwrap();
	let mut genome = HashMap::new();
	for entry in fastq.records() {
		let chr = entry.unwrap();
		genome.insert(chr.id().unwrap().to_owned(), chr.seq().to_owned());
	}

    let (child_in, child_out)= mpsc::channel();

    thread::spawn(move || {
	let bam = bam::Reader::from_path(&sam_path).unwrap();
	let mut R = 0;
	for r in bam.records() {
		let read = r.unwrap();
		if read.is_unmapped() == false { continue; }
		if read.seq().len() < anchor_len * 2 { continue; }
		// TODO: Extract anchors from both ends of read and write in
		// interleaved FASTA format to the stdin of Bowtie.
        R += 1;

        //write!(bowtie_stdin, ">{}_1\n{:?}\n", R, &read.seq().as_bytes()[..anchor_len]);
        let seq = String::from_utf8(read.seq().as_bytes()).unwrap();
        let tail = seq.len() - anchor_len ;
        let fas = ">".to_string()+&R.to_string()+"_1\n"+&seq[..anchor_len]+"\n>"+&R.to_string()+"_2\n"+&seq[tail..]+"\n";
        child_in.send(fas).unwrap();
    }
    });

    let mut bowtie = Command::new("bowtie")
		.args(&["-f", "-p1", "-v0", "-m1", "-B1", "--suppress", "5,6,7,8", &genome_path, "-"])
        .stdin(Stdio::piped()).stdout(Stdio::piped())
        .spawn().unwrap();

    let mut bowtie_stdin = bowtie.stdin.as_mut().unwrap();

    //println!("{}", child_out.recv().unwrap());
    //TODO: bowtie is not recognizing fata format
    // check the formatting
    // write and feed a tmpfile to bowtie maybe!?
    write!(bowtie_stdin, "{:?}", child_out.recv().unwrap());

     let mut bowtie_out = String::new();
       match bowtie.stdout.unwrap().read_to_string(&mut bowtie_out) {
           Err(why) => panic!("bowtie not running!"),
           Ok(_) => print!("bowtie worked!"),
       }

    for line in bowtie_out.lines() {
        println!("BOowtie stdou lines");
        println!("{}", line);
    }

    // match fas.stdin.unwrap().write_all(samres.as_bytes()) {
    //     Err(why) => panic!("samtools results not reaching fasta"),
    //     Ok(_) => print!("fasta recvied input from samtools"),
    // }

    // let mut res = String::new();
    //   match fas.stdout.unwrap().read_to_string(&mut res) {
    //       Err(why) => panic!("fasta not running!"),
    //       Ok(_) => print!("fasta subcommand worked!"),
    //   }
    //   println!("{:?}", res.len());
}
<|endoftext|>


<commit_before>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(1, bike_one.y.get());
    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}
<commit_msg>moved to rust 1.7 and added test for all_pos vec<commit_after>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(1, bike_one.y.get());
    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}

#[test]
fn it_can_log_all_positions() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(51, bike_one.x.get() + bike_one.y.get());

    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);

    assert_eq!(51, bike_one.x.get() + bike_one.y.get());

    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    let sum = all_pos.iter()
           .fold(0, |acc, &x| acc + x);

    assert_eq!(202, sum);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate capnp;
extern crate capnp_rpc;
extern crate cassandra;

use std::collections::HashMap;
use capnp::capability::{Server};
use capnp_rpc::ez_rpc::EzRpcServer;
use cassandra::*;

// this is generated automatically as part of the build process
// see build.rs
pub mod killranswers_capnp {
  include!(concat!(env!("OUT_DIR"), "/killranswers_capnp.rs"));
}
use killranswers_capnp::killr_answers;

// queries for prepared statements
// schema is managed in the python part of the app
// see the cqlengine Models
static CREATE_USER : &'static str = "insert into killranswers.user (user_id) values (?)";

struct KillrAnswersImpl {
    db: Session,
    queries: HashMap<String, PreparedStatement>,
}

impl KillrAnswersImpl {
    // returns a Boxed implemention
    fn new() -> Result<Box<KillrAnswersImpl>, CassandraError> {

        let mut cluster = Cluster::new();
        println!("Cluster created");
        cluster.set_contact_points("127.0.0.1").unwrap();
        println!("Setting protocol version");
        // cluster.set_protocol_version(3).unwrap();
        println!("connecting");
        let mut session = cluster.connect().unwrap();
        println!("Connected");
        // closure to prepare statement
        let mut queries = HashMap::new();

        println!("preparing");
        let mut prepared = try!(session.prepare(CREATE_USER));
        //
        println!("unwrapping and waiting");
        match prepared.wait() {
            Ok(prepared) => {
                let name = "CREATE_USER".to_string();
                queries.insert(name, prepared);
            }
            Err(err) => {
                println!("BAD NEWS FAIL");
                panic!(err);
            }
        }
        println!("new() done");
        Ok(Box::new(KillrAnswersImpl{ db: session, queries: queries }))
    }
}

impl killr_answers::Server for KillrAnswersImpl {
    // fn ask(&mut self, mut context: killr_answers::AskContext) {
    //     println!("Asking");
    // }
    fn register_user(&mut self, mut context: killr_answers::RegisterUserContext) {
        context.done();
    }

}

fn main() {
    println!("Starting up...");

    let rpc_server = EzRpcServer::new("127.0.0.1:6000").unwrap();
    let server = KillrAnswersImpl::new().unwrap();
    let ka = Box::new(killr_answers::ServerDispatch { server : server });
    //
    rpc_server.serve(ka);

    println!("Done");
}
<commit_msg>protocol 3, fixed scope problem with closing context"<commit_after>#[macro_use]
extern crate capnp;
extern crate capnp_rpc;
extern crate cassandra;

use std::collections::HashMap;
use capnp::capability::{Server};
use capnp_rpc::ez_rpc::EzRpcServer;
use cassandra::*;

// this is generated automatically as part of the build process
// see build.rs
pub mod killranswers_capnp {
  include!(concat!(env!("OUT_DIR"), "/killranswers_capnp.rs"));
}
use killranswers_capnp::killr_answers;

// queries for prepared statements
// schema is managed in the python part of the app
// see the cqlengine Models
static CREATE_USER : &'static str = "insert into killranswers.user (user_id) values (?)";

struct KillrAnswersImpl {
    db: Session,
    queries: HashMap<String, PreparedStatement>,
}

impl KillrAnswersImpl {
    // returns a Boxed implemention
    fn new() -> Result<Box<KillrAnswersImpl>, CassandraError> {

        let mut cluster = Cluster::new();
        println!("Cluster created");
        cluster.set_contact_points("127.0.0.1").unwrap();
        println!("Setting protocol version");
        cluster.set_protocol_version(3).unwrap();
        println!("connecting");
        let mut session = cluster.connect().unwrap();
        println!("Connected");
        // closure to prepare statement
        let mut queries = HashMap::new();

        println!("preparing");
        let mut prepared = try!(session.prepare(CREATE_USER));
        //
        println!("unwrapping and waiting");
        match prepared.wait() {
            Ok(prepared) => {
                let name = "CREATE_USER".to_string();
                queries.insert(name, prepared);
            }
            Err(err) => {
                println!("BAD NEWS FAIL");
                panic!(err);
            }
        }
        println!("new() done");
        Ok(Box::new(KillrAnswersImpl{ db: session, queries: queries }))
    }
}

impl killr_answers::Server for KillrAnswersImpl {
    // fn ask(&mut self, mut context: killr_answers::AskContext) {
    //     println!("Asking");
    // }
    fn register_user(&mut self, mut context: killr_answers::RegisterUserContext) {
        {
            let (params, mut results) = context.get();
            let user_id = params.get_user_id().unwrap();
            let q = self.queries.get(&"CREATE_USER".to_string()).unwrap();
            let mut q2 = q.bind();
            q2.bind_string(1, &user_id).unwrap();
            self.db.execute_statement(&q2).wait();
        }
        context.done();
    }

}

fn main() {
    println!("Starting up...");

    let rpc_server = EzRpcServer::new("127.0.0.1:6000").unwrap();
    let server = KillrAnswersImpl::new().unwrap();
    let ka = Box::new(killr_answers::ServerDispatch { server : server });
    //
    rpc_server.serve(ka);

    println!("Done");
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate hyper;
extern crate hyper_native_tls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate serde_json;
extern crate url;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;

use ring::digest;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs, AddChainRequest};

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    return pem::parse_many(data)
               .into_iter()
               .filter(|p| p.tag == "CERTIFICATE")
               .map(|p| p.contents)
               .collect::<Vec<_>>();
}

fn build_chain(http_client: &hyper::Client, cert: &[u8]) -> Vec<Vec<u8>> {
    let body = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("b64cert", &base64::encode(cert))
        .finish();
    let body_bytes = body.as_bytes();
    let response = http_client
        .post("https://crt.sh/gen-add-chain")
        .header(hyper::header::ContentType::form_url_encoded())
        .body(hyper::client::Body::BufBody(body_bytes, body_bytes.len()))
        .send()
        .unwrap();

    let add_chain_request: AddChainRequest = serde_json::from_reader(response).unwrap();
    return add_chain_request
               .chain
               .iter()
               .map(|c| base64::decode(c).unwrap())
               .collect();
}

fn main() {
    if env::args().len() == 1 {
        println!("Usage: {} <cert-or-chain.pem ...>",
                 env::args().next().unwrap());
        process::exit(1);
    }

    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    // TODO: timeout on the http_client, but for submit_cert_to_logs only, not build_chain
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in env::args().skip(1) {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = build_chain(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();

        // TODO: is there a better way to do this hex-encoding?
        println!("Find the cert on crt.sh: https://crt.sh?q={}",
                 digest::digest(&digest::SHA256, &chain[0])
                     .as_ref()
                     .iter()
                     .map(|b| format!("{:02X}", b))
                     .collect::<String>());
        println!();
        println!();
    }

}
<commit_msg>Print the URL before the table, more readable<commit_after>extern crate base64;
extern crate hyper;
extern crate hyper_native_tls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate serde_json;
extern crate url;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;

use ring::digest;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs, AddChainRequest};

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    return pem::parse_many(data)
               .into_iter()
               .filter(|p| p.tag == "CERTIFICATE")
               .map(|p| p.contents)
               .collect::<Vec<_>>();
}

fn build_chain(http_client: &hyper::Client, cert: &[u8]) -> Vec<Vec<u8>> {
    let body = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("b64cert", &base64::encode(cert))
        .finish();
    let body_bytes = body.as_bytes();
    let response = http_client
        .post("https://crt.sh/gen-add-chain")
        .header(hyper::header::ContentType::form_url_encoded())
        .body(hyper::client::Body::BufBody(body_bytes, body_bytes.len()))
        .send()
        .unwrap();

    let add_chain_request: AddChainRequest = serde_json::from_reader(response).unwrap();
    return add_chain_request
               .chain
               .iter()
               .map(|c| base64::decode(c).unwrap())
               .collect();
}

fn main() {
    if env::args().len() == 1 {
        println!("Usage: {} <cert-or-chain.pem ...>",
                 env::args().next().unwrap());
        process::exit(1);
    }

    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    // TODO: timeout on the http_client, but for submit_cert_to_logs only, not build_chain
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in env::args().skip(1) {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = build_chain(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        // TODO: is there a better way to do this hex-encoding?
        println!("Find the cert on crt.sh: https://crt.sh?q={}",
                 digest::digest(&digest::SHA256, &chain[0])
                     .as_ref()
                     .iter()
                     .map(|b| format!("{:02X}", b))
                     .collect::<String>());

        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();
        println!();
        println!();
    }

}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
use std::iter::Peekable;
use std::process::{Command, ExitStatus};
use std::str::Chars;

extern crate itertools;
use itertools::Itertools;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
    Text(String),
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<Vec<Expr>> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'a> {
    input: &'a str,
    iter: Peekable<Chars<'a>>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum ParseError {
    UnclosedDelimiter(char),
    UnexpectedChar(char),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::UnclosedDelimiter(c) => write!(f, "unclosed delimiter: {}", c),
            ParseError::UnexpectedChar(c) => write!(f, "unexpected character: {}", c),
        }
    }
}

impl<'a> Lexer<'a> {
    fn new(input: &str) -> Lexer {
        Lexer {
            input: input,
            iter: input.chars().peekable(),
        }
    }

    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().cloned()
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn is_unquoted_text(c: char) -> bool {
        match c {
            'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '+' | '/' | '_' | '.' | ',' => true,
            _ => false,
        }
    }

    fn lex_whitespace(&mut self) -> Result<Token, ParseError> {
        while let Some(c) = self.peek_char() {
            if !Lexer::is_whitespace(c) { break; }
            self.iter.next();
        }

        Ok(Token::Whitespace)
    }

    fn lex_unquoted_text(&mut self) -> Result<Token, ParseError> {
        let mut text = String::new();

        while let Some(c) = self.peek_char() {
            if !Lexer::is_unquoted_text(c) { break; }
            text.push(c);
            self.iter.next();
        }

        Ok(Token::Text(text))
    }

    fn lex_quoted_text(&mut self) -> Result<Token, ParseError> {
        let delimiter = self.peek_char().unwrap();
        self.iter.next();

        let mut text = String::new();

        loop {
            if let Some(c) = self.peek_char() {
                self.iter.next();
                match c {
                    '\\' => { unimplemented!() },
                    c if c == delimiter => break,
                    c => { text.push(c) },
                }
            } else {
                return Err(ParseError::UnclosedDelimiter(delimiter))
            }
        }

        Ok(Token::Text(text))
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result<Token, ParseError>;

    fn next(&mut self) -> Option<Result<Token, ParseError>> {
        self.peek_char().map(|peek_char| {
            match peek_char {
                c if Lexer::is_whitespace(c)    => self.lex_whitespace(),
                c if Lexer::is_unquoted_text(c) => self.lex_unquoted_text(),
                '\r' | '\n'                     => { self.iter.next(); Ok(Token::Newline) },
                '"' | '\''                      => self.lex_quoted_text(),
                c                               => Err(ParseError::UnexpectedChar(c))
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'a> {
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> Result<Ast, ParseError> {
        if let Some(token_result) = self.lexer.next() {
            let token = try!(token_result);
            match token {
                Token::Whitespace | Token::Newline => self.parse(),
                Token::Text(command) => self.parse_call(command),
            }
        } else {
            Ok(Ast::Empty)
        }
    }

    fn parse_call(&mut self, command: String) -> Result<Ast, ParseError> {
        let mut args = vec![];
        let mut current_arg = vec![];

        for token_result in &mut self.lexer {
            let token = try!(token_result);
            match token {
                Token::Newline => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                    }
                    break;
                },

                Token::Whitespace => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                        current_arg = vec![];
                    }
                },

                Token::Text(text) => {
                    current_arg.push(Expr::Text(text));
                },
            }
        }

        Ok(Ast::Call { command: command, args: args })
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(cmd: &'static str, result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "shroom: {}: {}", cmd, e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code("cd", std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code("cd", std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "shroom: cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "shroom: exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            // Evaluate argument expressions.
            let evaluated_args: Vec<String> = args.iter().map(|arg| {
                arg.iter().map(|expr| {
                    match *expr {
                        Expr::Text(ref text) => text,
                    }
                }).join("")
            }).collect();

            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "shroom: {}: not enough arguments",
                             builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "shroom: {}: too many arguments",
                             builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(&evaluated_args)
                }
            } else {
                match Command::new(command).args(&evaluated_args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}: {}", command, e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();

        match Parser::new(&line).parse() {
            Ok(ast) => {
                let exit_code = execute(&ast);
                if exit_code != 0 {
                    println!("shroom: exit code: {}", exit_code);
                }
            },

            Err(parse_error) => {
                println!("shroom: parse error: {}", parse_error);
            },
        }

        line.clear();
    }
}
<commit_msg>Simplify lexing with itertools.<commit_after>use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
use std::iter::Peekable;
use std::process::{Command, ExitStatus};
use std::str::Chars;

extern crate itertools;
use itertools::Itertools;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
    Text(String),
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<Vec<Expr>> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'a> {
    input: &'a str,
    iter: Peekable<Chars<'a>>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum ParseError {
    UnclosedDelimiter(char),
    UnexpectedChar(char),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::UnclosedDelimiter(c) => write!(f, "unclosed delimiter: {}", c),
            ParseError::UnexpectedChar(c) => write!(f, "unexpected character: {}", c),
        }
    }
}

impl<'a> Lexer<'a> {
    fn new(input: &str) -> Lexer {
        Lexer {
            input: input,
            iter: input.chars().peekable(),
        }
    }

    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().cloned()
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn is_unquoted_text(c: char) -> bool {
        match c {
            'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '+' | '/' | '_' | '.' | ',' => true,
            _ => false,
        }
    }

    fn lex_whitespace(&mut self) -> Result<Token, ParseError> {
        for _ in self.iter.take_while_ref(|c| Lexer::is_whitespace(*c)) {}
        Ok(Token::Whitespace)
    }

    fn lex_unquoted_text(&mut self) -> Result<Token, ParseError> {
        let text = self.iter.take_while_ref(|c| Lexer::is_unquoted_text(*c)).collect();
        Ok(Token::Text(text))
    }

    fn lex_quoted_text(&mut self) -> Result<Token, ParseError> {
        let delimiter = self.peek_char().unwrap();
        self.iter.next();

        let mut text = String::new();

        loop {
            if let Some(c) = self.peek_char() {
                self.iter.next();
                match c {
                    '\\' => { unimplemented!() },
                    c if c == delimiter => break,
                    c => { text.push(c) },
                }
            } else {
                return Err(ParseError::UnclosedDelimiter(delimiter))
            }
        }

        Ok(Token::Text(text))
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result<Token, ParseError>;

    fn next(&mut self) -> Option<Result<Token, ParseError>> {
        self.peek_char().map(|peek_char| {
            match peek_char {
                c if Lexer::is_whitespace(c)    => self.lex_whitespace(),
                c if Lexer::is_unquoted_text(c) => self.lex_unquoted_text(),
                '\r' | '\n'                     => { self.iter.next(); Ok(Token::Newline) },
                '"' | '\''                      => self.lex_quoted_text(),
                c                               => Err(ParseError::UnexpectedChar(c))
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'a> {
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> Result<Ast, ParseError> {
        if let Some(token_result) = self.lexer.next() {
            let token = try!(token_result);
            match token {
                Token::Whitespace | Token::Newline => self.parse(),
                Token::Text(command) => self.parse_call(command),
            }
        } else {
            Ok(Ast::Empty)
        }
    }

    fn parse_call(&mut self, command: String) -> Result<Ast, ParseError> {
        let mut args = vec![];
        let mut current_arg = vec![];

        for token_result in &mut self.lexer {
            let token = try!(token_result);
            match token {
                Token::Newline => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                    }
                    break;
                },

                Token::Whitespace => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                        current_arg = vec![];
                    }
                },

                Token::Text(text) => {
                    current_arg.push(Expr::Text(text));
                },
            }
        }

        Ok(Ast::Call { command: command, args: args })
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(cmd: &'static str, result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "shroom: {}: {}", cmd, e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code("cd", std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code("cd", std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "shroom: cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "shroom: exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            // Evaluate argument expressions.
            let evaluated_args: Vec<String> = args.iter().map(|arg| {
                arg.iter().map(|expr| {
                    match *expr {
                        Expr::Text(ref text) => text,
                    }
                }).join("")
            }).collect();

            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "shroom: {}: not enough arguments",
                             builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "shroom: {}: too many arguments",
                             builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(&evaluated_args)
                }
            } else {
                match Command::new(command).args(&evaluated_args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}: {}", command, e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();

        match Parser::new(&line).parse() {
            Ok(ast) => {
                let exit_code = execute(&ast);
                if exit_code != 0 {
                    println!("shroom: exit code: {}", exit_code);
                }
            },

            Err(parse_error) => {
                println!("shroom: parse error: {}", parse_error);
            },
        }

        line.clear();
    }
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::process::exit;
use std::os::unix::process::CommandExt;

fn main() {
    let err = Command::new("java")
        .arg("-Xms512m")
        .arg("-Xmx1536m")
        .arg("-Xss2m")
        .args(&["-jar", "/Users/dnw/.sbt/launchers/0.13.13/sbt-launch.jar"])
        .arg("shell")
        .exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        exit(err);
    }
    exit(-1)
}
<commit_msg>Make launcher path dependent on HOME<commit_after>use std::process::Command;
use std::process::exit;
use std::os::unix::process::CommandExt;

fn main() {
    let home = std::env::var("HOME").unwrap();
    let err = Command::new("java")
        .arg("-Xms512m")
        .arg("-Xmx1536m")
        .arg("-Xss2m")
        .args(&["-jar", &format!("{}/.sbt/launchers/0.13.13/sbt-launch.jar", home)])
        .arg("shell")
        .exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        exit(err);
    }
    exit(-1)
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// 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.
//
//! Alacritty - The GPU Enhanced Terminal
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]

#[macro_use]
extern crate alacritty;

#[macro_use]
extern crate log;

use std::error::Error;
use std::sync::Arc;

use alacritty::cli;
use alacritty::config::{self, Config};
use alacritty::display::Display;
use alacritty::event;
use alacritty::event_loop::{self, EventLoop, Msg};
use alacritty::logging;
use alacritty::sync::FairMutex;
use alacritty::term::{Term};
use alacritty::tty::{self, process_should_exit};
use alacritty::util::fmt::Red;

fn main() {
    // Load command line options and config
    let options = cli::Options::load();
    let config = load_config(&options);

    // Run alacritty
    if let Err(err) = run(config, options) {
        die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err));
    }

    info!("Goodbye.");
}

/// Load configuration
///
/// If a configuration file is given as a command line argument we don't
/// generate a default file. If an empty configuration file is given, i.e.
/// /dev/null, we load the compiled-in defaults.
fn load_config(options: &cli::Options) -> Config {
    let config_path = options.config_path()
        .or_else(|| Config::installed_config())
        .unwrap_or_else(|| {
            Config::write_defaults()
                .unwrap_or_else(|err| die!("Write defaults config failure: {}", err))
        });

    Config::load_from(&*config_path).unwrap_or_else(|err| {
        match err {
            config::Error::NotFound => {
                die!("Config file not found at: {}", config_path.display());
            },
            config::Error::Empty => {
                err_println!("Empty config; Loading defaults");
                Config::default()
            },
            _ => die!("{}", err),
        }
    })
}

/// Run Alacritty
///
/// Creates a window, the terminal state, pty, I/O event loop, input processor,
/// config change monitor, and runs the main display loop.
fn run(mut config: Config, options: cli::Options) -> Result<(), Box<Error>> {
    // Initialize the logger first as to capture output from other subsystems
    logging::initialize(&options)?;

    info!("Welcome to Alacritty.");

    // Create a display.
    //
    // The display manages a window and can draw the terminal
    let mut display = Display::new(&config, &options)?;

    info!(
        "PTY Dimensions: {:?} x {:?}",
        display.size().lines(),
        display.size().cols()
    );

    // Create the terminal
    //
    // This object contains all of the state about what's being displayed. It's
    // wrapped in a clonable mutex since both the I/O loop and display need to
    // access it.
    let terminal = Term::new(&config, display.size().to_owned());
    let terminal = Arc::new(FairMutex::new(terminal));

    // Find the window ID for setting $WINDOWID
    let window_id = display.get_window_id();

    // Create the pty
    //
    // The pty forks a process to run the shell on the slave side of the
    // pseudoterminal. A file descriptor for the master side is retained for
    // reading/writing to the shell.
    let mut pty = tty::new(&config, &options, display.size(), window_id);

    // Create the pseudoterminal I/O loop
    //
    // pty I/O is ran on another thread as to not occupy cycles used by the
    // renderer and input processing. Note that access to the terminal state is
    // synchronized since the I/O loop updates the state, and the display
    // consumes it periodically.
    let event_loop = EventLoop::new(
        terminal.clone(),
        display.notifier(),
        pty.reader(),
        options.ref_test,
    );

    // The event loop channel allows write requests from the event processor
    // to be sent to the loop and ultimately written to the pty.
    let loop_tx = event_loop.channel();

    // Event processor
    //
    // Need the Rc<RefCell<_>> here since a ref is shared in the resize callback
    let mut processor = event::Processor::new(
        event_loop::Notifier(event_loop.channel()),
        display.resize_channel(),
        &options,
        &config,
        options.ref_test,
        display.size().to_owned(),
    );

    // Create a config monitor when config was loaded from path
    //
    // The monitor watches the config file for changes and reloads it. Pending
    // config changes are processed in the main loop.
    let config_monitor = match (options.live_config_reload, config.live_config_reload()) {
        // Start monitor if CLI flag says yes
        (Some(true), _) |
        // Or if no CLI flag was passed and the config says yes
        (None, true) => config.path()
                .map(|path| config::Monitor::new(path, display.notifier())),
        // Otherwise, don't start the monitor
        _ => None,
    };

    // Kick off the I/O thread
    let io_thread = event_loop.spawn(None);

    // Main display loop
    loop {
        // Process input and window events
        let mut terminal = processor.process_events(&terminal, display.window());

        // Handle config reloads
        config_monitor.as_ref()
            .and_then(|monitor| monitor.pending_config())
            .map(|new_config| {
                config = new_config;
                display.update_config(&config);
                processor.update_config(&config);
                terminal.update_config(&config);
                terminal.dirty = true;
            });

        // Maybe draw the terminal
        if terminal.needs_draw() {
            // Try to update the position of the input method editor
            display.update_ime_position(&terminal);
            // Handle pending resize events
            //
            // The second argument is a list of types that want to be notified
            // of display size changes.
            display.handle_resize(&mut terminal, &mut [&mut pty, &mut processor]);

            // Draw the current state of the terminal
            display.draw(terminal, &config, processor.selection.as_ref());
        }

        // Begin shutdown if the flag was raised.
        if process_should_exit() {
            break;
        }
    }

    loop_tx.send(Msg::Shutdown).expect("Error sending shutdown to event loop");

    // FIXME patch notify library to have a shutdown method
    // config_reloader.join().ok();

    // Wait for the I/O thread thread to finish
    let _ = io_thread.join();

    Ok(())
}
<commit_msg>Log where config was loaded from<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// 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.
//
//! Alacritty - The GPU Enhanced Terminal
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]

#[macro_use]
extern crate alacritty;

#[macro_use]
extern crate log;

use std::error::Error;
use std::sync::Arc;

use alacritty::cli;
use alacritty::config::{self, Config};
use alacritty::display::Display;
use alacritty::event;
use alacritty::event_loop::{self, EventLoop, Msg};
use alacritty::logging;
use alacritty::sync::FairMutex;
use alacritty::term::{Term};
use alacritty::tty::{self, process_should_exit};
use alacritty::util::fmt::Red;

fn main() {
    // Load command line options and config
    let options = cli::Options::load();
    let config = load_config(&options);

    // Run alacritty
    if let Err(err) = run(config, options) {
        die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err));
    }

    info!("Goodbye.");
}

/// Load configuration
///
/// If a configuration file is given as a command line argument we don't
/// generate a default file. If an empty configuration file is given, i.e.
/// /dev/null, we load the compiled-in defaults.
fn load_config(options: &cli::Options) -> Config {
    let config_path = options.config_path()
        .or_else(|| Config::installed_config())
        .unwrap_or_else(|| {
            Config::write_defaults()
                .unwrap_or_else(|err| die!("Write defaults config failure: {}", err))
        });

    Config::load_from(&*config_path).unwrap_or_else(|err| {
        match err {
            config::Error::NotFound => {
                die!("Config file not found at: {}", config_path.display());
            },
            config::Error::Empty => {
                err_println!("Empty config; Loading defaults");
                Config::default()
            },
            _ => die!("{}", err),
        }
    })
}

/// Run Alacritty
///
/// Creates a window, the terminal state, pty, I/O event loop, input processor,
/// config change monitor, and runs the main display loop.
fn run(mut config: Config, options: cli::Options) -> Result<(), Box<Error>> {
    // Initialize the logger first as to capture output from other subsystems
    logging::initialize(&options)?;

    info!("Welcome to Alacritty.");
    config.path().map(|config_path| {
        info!("Configuration loaded from {}", config_path.display());
    });

    // Create a display.
    //
    // The display manages a window and can draw the terminal
    let mut display = Display::new(&config, &options)?;

    info!(
        "PTY Dimensions: {:?} x {:?}",
        display.size().lines(),
        display.size().cols()
    );

    // Create the terminal
    //
    // This object contains all of the state about what's being displayed. It's
    // wrapped in a clonable mutex since both the I/O loop and display need to
    // access it.
    let terminal = Term::new(&config, display.size().to_owned());
    let terminal = Arc::new(FairMutex::new(terminal));

    // Find the window ID for setting $WINDOWID
    let window_id = display.get_window_id();

    // Create the pty
    //
    // The pty forks a process to run the shell on the slave side of the
    // pseudoterminal. A file descriptor for the master side is retained for
    // reading/writing to the shell.
    let mut pty = tty::new(&config, &options, display.size(), window_id);

    // Create the pseudoterminal I/O loop
    //
    // pty I/O is ran on another thread as to not occupy cycles used by the
    // renderer and input processing. Note that access to the terminal state is
    // synchronized since the I/O loop updates the state, and the display
    // consumes it periodically.
    let event_loop = EventLoop::new(
        terminal.clone(),
        display.notifier(),
        pty.reader(),
        options.ref_test,
    );

    // The event loop channel allows write requests from the event processor
    // to be sent to the loop and ultimately written to the pty.
    let loop_tx = event_loop.channel();

    // Event processor
    //
    // Need the Rc<RefCell<_>> here since a ref is shared in the resize callback
    let mut processor = event::Processor::new(
        event_loop::Notifier(event_loop.channel()),
        display.resize_channel(),
        &options,
        &config,
        options.ref_test,
        display.size().to_owned(),
    );

    // Create a config monitor when config was loaded from path
    //
    // The monitor watches the config file for changes and reloads it. Pending
    // config changes are processed in the main loop.
    let config_monitor = match (options.live_config_reload, config.live_config_reload()) {
        // Start monitor if CLI flag says yes
        (Some(true), _) |
        // Or if no CLI flag was passed and the config says yes
        (None, true) => config.path()
                .map(|path| config::Monitor::new(path, display.notifier())),
        // Otherwise, don't start the monitor
        _ => None,
    };

    // Kick off the I/O thread
    let io_thread = event_loop.spawn(None);

    // Main display loop
    loop {
        // Process input and window events
        let mut terminal = processor.process_events(&terminal, display.window());

        // Handle config reloads
        config_monitor.as_ref()
            .and_then(|monitor| monitor.pending_config())
            .map(|new_config| {
                config = new_config;
                display.update_config(&config);
                processor.update_config(&config);
                terminal.update_config(&config);
                terminal.dirty = true;
            });

        // Maybe draw the terminal
        if terminal.needs_draw() {
            // Try to update the position of the input method editor
            display.update_ime_position(&terminal);
            // Handle pending resize events
            //
            // The second argument is a list of types that want to be notified
            // of display size changes.
            display.handle_resize(&mut terminal, &mut [&mut pty, &mut processor]);

            // Draw the current state of the terminal
            display.draw(terminal, &config, processor.selection.as_ref());
        }

        // Begin shutdown if the flag was raised.
        if process_should_exit() {
            break;
        }
    }

    loop_tx.send(Msg::Shutdown).expect("Error sending shutdown to event loop");

    // FIXME patch notify library to have a shutdown method
    // config_reloader.join().ok();

    // Wait for the I/O thread thread to finish
    let _ = io_thread.join();

    Ok(())
}
<|endoftext|>


<commit_before>
#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL(i32),
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL(0); 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
			},
			_ => {},
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL(5),
		InstructionSet::PSH, InstructionSet::VAL(6),
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		vm.eval(vm.fetch());
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<commit_msg>All isntructions are supported and function as described<commit_after>
#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL{value: i32},
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL{value:0}; 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
				//[DEBUG]
				println!("PSH {0}", match self.program[self.ip] {InstructionSet::VAL{value} => value, _=> 0,});
			},
			POP => {
				let val_popped = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;
				println!("POP {0}", val_popped);
			},
			ADD => {
				// first we pop the stack and store it as a
				let a = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				// we then pop the top of the stack and store it as b
				let b = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				//[DEBUG]
				println!("ADD {0}; {1}", a, b);

				// we then add the result and push it to the stack
				let result = b + a;
				self.sp += 1; // increment stack pointer **before**
				self.stack[self.sp as usize] = InstructionSet::VAL{value: result}; // set the value to the top of the stack

			},
			_ => println!("Instruction does not exist in instruction set."),
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL{value: 5},
		InstructionSet::PSH, InstructionSet::VAL{value: 6},
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		let instr = vm.fetch();
		vm.eval(instr);
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<|endoftext|>


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(static_in_const)]

#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session};
use rustc::session::config::{Input, ErrorOutputType};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

use clippy_lints::utils::cargo;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        ClippyCompilerCalls {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(&mut self,
                      matches: &getopts::Matches,
                      sopts: &config::Options,
                      cfg: &ast::CrateConfig,
                      descriptions: &rustc_errors::registry::Registry,
                      output: ErrorOutputType)
                      -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(&mut self,
                matches: &getopts::Matches,
                sopts: &config::Options,
                cfg: &ast::CrateConfig,
                odir: &Option<PathBuf>,
                ofile: &Option<PathBuf>,
                descriptions: &rustc_errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(&mut self,
                     matches: &getopts::Matches,
                     sess: &Session,
                     input: &Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        self.default.late_callback(matches, sess, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed").span);
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry { early_lint_passes,
                                                           late_lint_passes,
                                                           lint_groups,
                                                           llvm_passes,
                                                           attributes,
                                                           mir_passes,
                                                           .. } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.mir_passes.borrow_mut().extend(mir_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps");

    if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
        // this arm is executed on the initial call to `cargo clippy`

        if std::env::args().any(|a| a == "--help" || a == "-h") {
            show_help();
            return;
        }

        let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path="));

        let mut metadata = cargo::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).expect("could not obtain cargo metadata");

        assert_eq!(metadata.version, 1);

        let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));

        let current_dir = std::env::current_dir();

        let package_index = metadata.packages.iter()
            .position(|package| {
                let package_manifest_path = Path::new(&package.manifest_path);
                if let Some(ref manifest_path) = manifest_path {
                    package_manifest_path == manifest_path
                } else {
                    let current_dir = current_dir.as_ref().expect("could not read current directory");
                    let package_manifest_directory = package_manifest_path.parent().expect("could not find parent directory of package manifest");
                    package_manifest_directory == current_dir
                }
            })
            .expect("could not find matching package");
        let package = metadata.packages.remove(package_index);
        for target in package.targets {
            let args = std::env::args().skip(2);
            if let Some(first) = target.kind.get(0) {
                if target.kind.len() > 1 || first.ends_with("lib") {
                    if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args), &dep_path) {
                        std::process::exit(code);
                    }
                } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                    if let Err(code) = process(vec![format!("--{}", first), target.name].into_iter().chain(args), &dep_path) {
                        std::process::exit(code);
                    }
                }
            } else {
                panic!("badly formatted cargo metadata: target::kind is an empty array");
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` env var set to itself

        let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
        let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
        let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
            format!("{}/toolchains/{}", home, toolchain)
        } else {
            option_env!("SYSROOT")
                .map(|s| s.to_owned())
                .or(Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned()))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust")
        };

        // this conditional check for the --sysroot flag is there so users can call `cargo-clippy` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
            env::args().collect()
        } else {
            env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect()
        };

        // this check ensures that dependencies are built but not linted and the final crate is
        // linted but not built
        args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);

        let mut ccc = ClippyCompilerCalls::new(env::args().any(|s| s == "-Zno-trans"));
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);

        if let Err(err_count) = result {
            if err_count > 0 {
                std::process::exit(1);
            }
        }
    }
}

fn process<P, I>(old_args: I, dep_path: P) -> Result<(), i32>
    where P: AsRef<Path>,
          I: Iterator<Item = String>
{

    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("-L".to_owned());
    args.push(dep_path.as_ref().to_string_lossy().into_owned());
    args.push("-Zno-trans".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC", path)
        .spawn().expect("could not run cargo")
        .wait().expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<commit_msg>fixed #1331<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(static_in_const)]

#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session};
use rustc::session::config::{Input, ErrorOutputType};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

use clippy_lints::utils::cargo;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        ClippyCompilerCalls {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(&mut self,
                      matches: &getopts::Matches,
                      sopts: &config::Options,
                      cfg: &ast::CrateConfig,
                      descriptions: &rustc_errors::registry::Registry,
                      output: ErrorOutputType)
                      -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(&mut self,
                matches: &getopts::Matches,
                sopts: &config::Options,
                cfg: &ast::CrateConfig,
                odir: &Option<PathBuf>,
                ofile: &Option<PathBuf>,
                descriptions: &rustc_errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(&mut self,
                     matches: &getopts::Matches,
                     sess: &Session,
                     input: &Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        self.default.late_callback(matches, sess, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed").span);
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry { early_lint_passes,
                                                           late_lint_passes,
                                                           lint_groups,
                                                           llvm_passes,
                                                           attributes,
                                                           mir_passes,
                                                           .. } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.mir_passes.borrow_mut().extend(mir_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps");

    if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
        // this arm is executed on the initial call to `cargo clippy`

        if std::env::args().any(|a| a == "--help" || a == "-h") {
            show_help();
            return;
        }

        let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path="));

        let mut metadata = cargo::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).expect("could not obtain cargo metadata");

        assert_eq!(metadata.version, 1);

        let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));

        let current_dir = std::env::current_dir();

        let package_index = metadata.packages.iter()
            .position(|package| {
                let package_manifest_path = Path::new(&package.manifest_path);
                if let Some(ref manifest_path) = manifest_path {
                    package_manifest_path == manifest_path
                } else {
                    let current_dir = current_dir.as_ref().expect("could not read current directory");
                    let package_manifest_directory = package_manifest_path.parent().expect("could not find parent directory of package manifest");
                    package_manifest_directory == current_dir
                }
            })
            .expect("could not find matching package");
        let package = metadata.packages.remove(package_index);
        for target in package.targets {
            let args = std::env::args().skip(2);
            if let Some(first) = target.kind.get(0) {
                if target.kind.len() > 1 || first.ends_with("lib") {
                    if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args), &dep_path) {
                        std::process::exit(code);
                    }
                } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                    if let Err(code) = process(vec![format!("--{}", first), target.name].into_iter().chain(args), &dep_path) {
                        std::process::exit(code);
                    }
                }
            } else {
                panic!("badly formatted cargo metadata: target::kind is an empty array");
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` env var set to itself

        let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
        let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
        let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
            format!("{}/toolchains/{}", home, toolchain)
        } else {
            option_env!("SYSROOT")
                .map(|s| s.to_owned())
                .or(Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned()))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust")
        };

        // this conditional check for the --sysroot flag is there so users can call `cargo-clippy` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
            env::args().collect()
        } else {
            env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect()
        };

        // this check ensures that dependencies are built but not linted and the final crate is
        // linted but not built
        let clippy_enabled = env::args().any(|s| s == "-Zno-trans");

        if clippy_enabled {
            args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
        }

        let mut ccc = ClippyCompilerCalls::new(clippy_enabled);
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);

        if let Err(err_count) = result {
            if err_count > 0 {
                std::process::exit(1);
            }
        }
    }
}

fn process<P, I>(old_args: I, dep_path: P) -> Result<(), i32>
    where P: AsRef<Path>,
          I: Iterator<Item = String>
{

    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("-L".to_owned());
    args.push(dep_path.as_ref().to_string_lossy().into_owned());
    args.push("-Zno-trans".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC", path)
        .spawn().expect("could not run cargo")
        .wait().expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<|endoftext|>