<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::swap;
use std::thread;
use std::sync::Arc;
use std::path::Path;
use std::io::prelude::*;
use std::fs;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::FromRawFd;
use std::str;
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;
extern crate subprocess;
extern crate regex;

#[macro_use]
extern crate shells;

use subprocess::{Exec, Popen, PopenConfig, Redirection};
use bio::alphabets;
use bio::alphabets::dna::alphabet;
use regex::Regex;

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());

      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_reads(bam_file, genome, anchor_len);
  }
}

// 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) {
          	swap(&mut chr, &mut mchr);
          	swap(&mut pos, &mut mpos);
          	swap(&mut rlen, &mut mrlen);
          	swap(&mut strand, &mut mstrand);
        }
        if mstrand == '+' { mstrand = '-';}
        else { mstrand = '+'; }
      }

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

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

          if mstrand == '-' { mstrand = '+';} else { mstrand = '-'; }
          if strand  == '-' { strand  = '+';} else { strand  = '-'; }
          	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, anchor_len: usize) {

	let fastq = bio::io::fasta::Reader::from_file(format!("{}.fa", genome_path)).unwrap();
	println!("Reading reference genome into memory...");

	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());
	}

    println!("Splitting unaligned reads into {} bp anchors and aligning against the genome...", anchor_len);
    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_in = bowtie.stdin.unwrap();
	let mut bowtie_out = BufReader::new(bowtie.stdout.unwrap());

	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;
	    let seq = read.seq().as_bytes();
	    let tail = seq.len() - anchor_len;
        write!(bowtie_in, ">{}/1_{}\n{}\n>{}/2_{}\n{}", R, unsafe { str::from_utf8_unchecked(&seq)}, unsafe { str::from_utf8_unchecked(&seq[..anchor_len])}, R, unsafe { str::from_utf8_unchecked(&seq)}, unsafe { str::from_utf8_unchecked(&seq[tail..]) });
	    }
    });

    let mut evidence: Vec<Evidence> = Vec::new();
    //let mut prev : Vec<&str> = Vec::new();

    for line in bowtie_out.lines() {
        let ln = line.unwrap();
        let cols: Vec<&str> = ln.split('\t').collect();
        let mut prev : Vec<&str> = Vec::new();
        if prev.is_empty() { prev = cols.clone(); }

        let mut frag_id = cols[1];
        let mut chr = prev[2]; let mut mchr = cols[2];
        let mut strand  = prev[1] == "+";
        let mut mstrand = cols[1] == "+";

        let mut pos:  usize  = cols[3].parse().unwrap();
        let mut mpos: usize  = prev[3].parse().unwrap();
        let mut sqtmp: Vec<&str> = prev[0].split('_').collect();
        let mut seq  = sqtmp[1];
        let full_len: usize = seq.len();

        if chr == mchr && (pos - mpos) < (full_len - anchor_len) + 10 { continue; }

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

        if chr > mchr || (chr == mchr && pos > mpos) {
        	swap(&mut chr, &mut mchr);
        	swap(&mut pos, &mut mpos);
          	if mstrand == false { mstrand = true ;} else { mstrand = false ; }
          	if strand  == false { strand  = true ;} else { strand  = false ; }
          	swap(&mut strand, &mut mstrand);

        	let seq = String::from_utf8(bio::alphabets::dna::revcomp(seq.as_bytes())).unwrap();
        	println!("Reverse\t:{:?}", seq);
        }

        // If the read is at the very edge of a chromosome, ignore it.
		if (pos + full_len ) >= genome[chr].len() { continue; }
		if (mpos + full_len) >= genome[mchr].len(){ continue; }
     }
}
<commit_msg>detecting breakpoints<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::swap;
use std::thread;
use std::sync::Arc;
use std::path::Path;
use std::io::prelude::*;
use std::fs;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::FromRawFd;
use std::str;
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;
extern crate subprocess;
extern crate regex;

#[macro_use]
extern crate shells;

use subprocess::{Exec, Popen, PopenConfig, Redirection};
use bio::alphabets;
use bio::alphabets::dna::alphabet;
use regex::Regex;

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());

      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_reads(bam_file, genome, anchor_len);
  }
}

// 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) {
          	swap(&mut chr, &mut mchr);
          	swap(&mut pos, &mut mpos);
          	swap(&mut rlen, &mut mrlen);
          	swap(&mut strand, &mut mstrand);
        }
        if mstrand == '+' { mstrand = '-';}
        else { mstrand = '+'; }
      }

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

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

          if mstrand == '-' { mstrand = '+';} else { mstrand = '-'; }
          if strand  == '-' { strand  = '+';} else { strand  = '-'; }
          	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, anchor_len: usize) {

	let fastq = bio::io::fasta::Reader::from_file(format!("{}.fa", genome_path)).unwrap();
	println!("Reading reference genome into memory...");

	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());
	}

    println!("Splitting unaligned reads into {} bp anchors and aligning against the genome...", anchor_len);
    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_in = bowtie.stdin.unwrap();
	let mut bowtie_out = BufReader::new(bowtie.stdout.unwrap());

	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 read id from BAM record and make proper fasta header
			// TODO: repace R with the above created ID
	        R += 1;
	    let seq = read.seq().as_bytes();
	    let tail = seq.len() - anchor_len;
        write!(bowtie_in, ">{}/1_{}\n{}\n>{}/2_{}\n{}", R, unsafe { str::from_utf8_unchecked(&seq)}, unsafe { str::from_utf8_unchecked(&seq[..anchor_len])}, R, unsafe { str::from_utf8_unchecked(&seq)}, unsafe { str::from_utf8_unchecked(&seq[tail..]) });
	    }
    });

    let mut evidence: Vec<Evidence> = Vec::new();
    let mut prev : Vec<&str> = Vec::new(); //TODO: keep lifetime of this vector inside for-loop

    for line in bowtie_out.lines() {
        let ln = line.unwrap();
        let cols: Vec<&str> = ln.split('\t').collect();
		// TODO: lifetime error still occurs!
        let mut prev : Vec<&str> = Vec::new();
        if prev.is_empty() { prev = cols.to_owned(); }

        let mut frag_id = cols[1];
        let mut chr = prev[2]; let mut mchr = cols[2];
        let mut strand  = prev[1] == "+";
        let mut mstrand = cols[1] == "+";

        let mut pos:  usize  = cols[3].parse().unwrap();
        let mut mpos: usize  = prev[3].parse().unwrap();
        let mut sqtmp: Vec<&str> = prev[0].split('_').collect();
        let mut seq  = sqtmp[1];
        let full_len: usize = seq.len();

        if chr == mchr && (pos - mpos) < (full_len - anchor_len) + 10 { /*continue;*/ }

       	// skip mitochondria
	 	if chr.contains("chrM") || mchr.contains("chrM") { println!("Mitochondra...!"); continue; }

        if chr > mchr || (chr == mchr && pos > mpos) {
        	swap(&mut chr, &mut mchr);
        	swap(&mut pos, &mut mpos);
          	if mstrand == false { mstrand = true ;} else { mstrand = false ; }
          	if strand  == false { strand  = true ;} else { strand  = false ; }
          	swap(&mut strand, &mut mstrand);

        	let seq = String::from_utf8(bio::alphabets::dna::revcomp(seq.as_bytes())).unwrap();
        	//println!("Reverse\t:{:?}", seq);
        }

        // If the read is at the very edge of a chromosome, ignore it.
		if (pos + full_len ) >= genome[chr].len() { continue; }
		if (mpos + full_len) >= genome[mchr].len(){ continue; }

		let mut left_grch: String;
		if strand == true {
	 		left_grch = String::from_utf8(genome[chr][pos-1..pos+full_len-1].to_vec()).unwrap();
	 	} else {
	 		left_grch = String::from_utf8(bio::alphabets::dna::revcomp(&genome[chr][pos+anchor_len-full_len-1..pos+anchor_len-1])).unwrap();
	 	}

	 	let mut right_grch: String;
		if mstrand == true {
	 		right_grch = String::from_utf8(genome[chr][mpos+anchor_len-full_len..pos+full_len-1].to_vec()).unwrap();
	 	} else {
	 		right_grch = String::from_utf8(bio::alphabets::dna::revcomp(&genome[chr][mpos-1..mpos+full_len-1])).unwrap();
	 	}

	 	// Check that the read sequence is not too homologous on either side
		// of the breakpoint.
		let mut left_match: f32 = 0.0;
	  	for k in full_len-anchor_len+1..full_len {
 			if seq.chars().nth(k) == left_grch.chars().nth(k){ left_match += 1.0; }
   		}
  		left_match = left_match /anchor_len as f32;

  		let mut right_match: f32 = 0.0;
	  	for k in 1..anchor_len {
 			if seq.chars().nth(k) == right_grch.chars().nth(k){ right_match += 1.0; }
   		}
  		right_match = right_match/anchor_len as f32;
		let max_homology = 0.7;

		if left_match >= max_homology || right_match >= max_homology { continue; }

		// Identify the breakpoint location that minimizes the number of
		// nucleotide mismatches between the read and the breakpoint flanks.
		let mut mismatches: Vec<usize> = vec![0; full_len - anchor_len + 1];
//		println!("How mary can be there? {:?}", mismatches.capacity());

		for k in 1..anchor_len+1 { if seq.chars().nth(k) != left_grch.chars().nth(k) {
		mismatches[anchor_len] += 1; }}

		for k in anchor_len..full_len+1 { if seq.chars().nth(k) != right_grch.chars().nth(k){
		mismatches[anchor_len] += 1; }}

		for bp in anchor_len..full_len+1 - anchor_len {
			let mut lmatch:usize = 0 ; let mut rmatch:usize = 0;
			if seq.chars().nth(bp) != left_grch.chars().nth(bp){ lmatch += 1; }
			if seq.chars().nth(bp) !=right_grch.chars().nth(bp){ rmatch += 1; }
			mismatches[bp] = mismatches[bp-1] + lmatch - rmatch;

		}
		let mut bp = 0;
		if !mismatches.is_empty() {
			//mismatches = mismatches.sort();
			bp = mismatches[0];
			}

		println!("{:?} breakpoint", bp);
//		println!("How mary are there? {:?}", mismatches.len());

    }
 	/* TEST VARAIBLES
    let chr = "chr7";
    let seq  = "atcgtagtcgtacgtagctagatgctagatgctag";
 	let full_len = seq.len();
 	let pos = full_len / 4;
 	let left_grch = "atgctatcgtagtcgtacgtagctagatgctagatgctagacgtagctagat";
  	let mut left_match = 0;
  	for k in (full_len-anchor_len+1..full_len) {
 		if seq.chars().nth(k) == left_grch.chars().nth(k){
  			left_match += 1;
  			println!("{:?}", seq.chars().nth(k).unwrap());
  		}
  	}
  	left_match = left_match/anchor_len;
 	println!("{:?}", left_match); */

 println!("End of function");
 println!("Hello World!");
}
<|endoftext|>


<commit_before>extern crate pcap;
extern crate spoof;

use spoof::layers::datalink::Ethernet;
use spoof::layers::network::{IPv4};
use spoof::layers::transport::{TCP, UDP};
use spoof::traits::{Chainable, Datalink, Network, NetworkLayer, TransportLayer};
use pcap::{Device, Capture};
use std::io::{self, BufRead, stdout, Write};

fn main() {
    let mut dev: Device = Device{name: String::from(""), desc: None};
    for device in pcap::Device::list().unwrap() {
        println!("Found device! {:?}", device);
        print!("Use?[y/n]:");
        stdout().flush();
        let mut line = String::new();
        let stdin = io::stdin();
        stdin.lock().read_line(&mut line).expect("Could not read line");
        if line.starts_with("y") {
            dev.name = device.name;
            dev.desc = device.desc;
            break;
        }
    }

    let mut cap = Capture::from_device(dev).unwrap()
        .promisc(true)
        .snaplen(65535)
        .open().unwrap();
    while let Ok(packet) = cap.next() {
        let e =  Ethernet::new(&packet).unwrap();
        match e.get_next_level() {
            NetworkLayer::IPv4 => {
                let ip = IPv4::new(&packet, e.get_end()).unwrap();
                match ip.get_next_level() {
                    TransportLayer::TCP => {
                        let tcp = TCP::new(&packet, ip.get_end()).unwrap();
                        println!("TCP {}:{} -> {}:{}",
                                 &ip.get_source_ip(), &tcp.src_port,
                                 &ip.get_destination_ip(), &tcp.dst_port);
                    },
                    TransportLayer::UDP => {
                        let udp = UDP::new(&packet, ip.get_end()).unwrap();
                        println!("UDP {}:{} -> {}:{}",
                                 &ip.get_source_ip(), &udp.src_port,
                                 &ip.get_destination_ip(), &udp.dst_port);
                    },
                    _ => {}
                }
            },
            _ => {
                println!("{} -> {} Cannot process type", e.get_source_mac(), e.get_destination_mac());
            }
        }
    }
}
<commit_msg>unwraping flush to remove warning<commit_after>extern crate pcap;
extern crate spoof;

use spoof::layers::datalink::Ethernet;
use spoof::layers::network::{IPv4};
use spoof::layers::transport::{TCP, UDP};
use spoof::traits::{Chainable, Datalink, Network, NetworkLayer, TransportLayer};
use pcap::{Device, Capture};
use std::io::{self, BufRead, stdout, Write};

fn main() {
    let mut dev: Device = Device{name: String::from(""), desc: None};
    for device in pcap::Device::list().unwrap() {
        println!("Found device! {:?}", device);
        print!("Use?[y/n]:");
        stdout().flush().unwrap();
        let mut line = String::new();
        let stdin = io::stdin();
        stdin.lock().read_line(&mut line).expect("Could not read line");
        if line.starts_with("y") {
            dev.name = device.name;
            dev.desc = device.desc;
            break;
        }
    }

    let mut cap = Capture::from_device(dev).unwrap()
        .promisc(true)
        .snaplen(65535)
        .open().unwrap();
    while let Ok(packet) = cap.next() {
        let e =  Ethernet::new(&packet).unwrap();
        match e.get_next_level() {
            NetworkLayer::IPv4 => {
                let ip = IPv4::new(&packet, e.get_end()).unwrap();
                match ip.get_next_level() {
                    TransportLayer::TCP => {
                        let tcp = TCP::new(&packet, ip.get_end()).unwrap();
                        println!("TCP {}:{} -> {}:{}",
                                 &ip.get_source_ip(), &tcp.src_port,
                                 &ip.get_destination_ip(), &tcp.dst_port);
                    },
                    TransportLayer::UDP => {
                        let udp = UDP::new(&packet, ip.get_end()).unwrap();
                        println!("UDP {}:{} -> {}:{}",
                                 &ip.get_source_ip(), &udp.src_port,
                                 &ip.get_destination_ip(), &udp.dst_port);
                    },
                    _ => {}
                }
            },
            _ => {
                println!("{} -> {} Cannot process type", e.get_source_mac(), e.get_destination_mac());
            }
        }
    }
}
<|endoftext|>


<commit_before>#![desc = "Constraint Satisfaction in Rust"]
#![license = "MIT"]
#![crate_id = "csar#0.2"]
#![crate_type = "lib"]

#![feature(struct_inherit)]

use std::fmt;
use std::cell::RefCell;
use std::collections::hashmap::HashMap;
use std::rc::{Rc,Weak};

pub struct Mod {
    vars: RefCell<Vec<Rc<FDVar>>>,
    propagators: RefCell<Vec<Rc<Box<Propagator>>>>,
    waiting: RefCell<HashMap<(uint, Event), Vec<uint>>>
}

// cannot use type Model = Rc<Mod> since that would forbid using impl Model
pub struct Model;

/// Representation of finite domains as a list of intervals, maintaining
/// min and max for easy/quick access
#[deriving(Clone)]
struct Dom {
    min: int,
    max: int,
    intervals: Vec<(int, int)>
}

/// Runtime checked mutability with borrowing
#[deriving(Clone)]
struct Domain {
    dom: RefCell<Dom>
}

trait Propagator {
    fn id(&self) -> uint;
    fn model(&self) -> Weak<Mod>;

    fn events(&self) -> Vec<(uint, Event)>;
    fn propagate(&self) -> Vec<uint>;

    fn register(&self) {
        for &(var, event) in self.events().iter() {
            self.model().upgrade().unwrap().add_waiting(var, event, self.id());
        }
    }

    fn unregister(&self) {
        for &(var, event) in self.events().iter() {
            self.model().upgrade().unwrap().del_waiting(var, event, self.id());
        }
    }
}

pub virtual struct Prop {
    id: uint,
    model: Weak<Mod>
}

pub struct Var;

#[deriving(Clone)]
pub struct FDVar {
    model: Weak<Mod>,
    id: uint,
    name: String,
    dom: Domain
}

#[deriving(Show,Hash,Eq,PartialEq)]
pub enum Event {
    Min,
    Max,
    Ins
}

#[allow(dead_code)]
impl Model {
    fn new() -> Rc<Mod> {
        Rc::new(Mod {
            vars: RefCell::new(Vec::new()),
            propagators: RefCell::new(Vec::new()),
            waiting: RefCell::new(HashMap::new())
        })
    }
}

impl Mod {
    fn add_var(&self, var: Rc<FDVar>) {
        self.vars.borrow_mut().push(var);
    }

    fn add_prop(&self, prop: Rc<Box<Propagator>>) {
        self.propagators.borrow_mut().push(prop);
    }

    fn add_waiting(&self, var: uint, event: Event, propagator: uint) {
        let mut waiting = self.waiting.borrow_mut();
        if waiting.contains_key(&(var, event)) {
            waiting.get_mut(&(var, event)).push(propagator);
        } else {
            waiting.insert((var, event), vec![propagator]);
        }
    }

    fn del_waiting(&self, var: uint, event: Event, propagator: uint) {
        self.waiting.borrow_mut().get_mut(&(var, event)).remove(propagator);
    }

    fn get_waiting(&self, var: uint, event: Event) -> Vec<uint> {
        let waiting = self.waiting.borrow();
        match waiting.find_copy(&(var, event)) {
            Some(vec) => vec,
            None => Vec::new()
        }
    }
}

#[allow(dead_code)]
impl Domain {
    /// Domain created with initial bounds
    fn new(min: int, max: int) -> Domain {
        Domain {
            dom: RefCell::new(Dom {
                     min: min,
                     max: max,
                     intervals: vec![(min, max)]
                 })
        }
    }

    fn set_min(&self, min: int) {
        let mut dom = self.dom.borrow_mut();
        if min < dom.min { return; }
        if min > dom.max { return; } // TODO failure via conditions
        loop {
            match dom.intervals.get(0) {
                // note that the breaks are for the loop, not the matching
                &(x, _) if min < x => { dom.min = x; break; },
                &(_, y) if min > y => { dom.intervals.shift(); },
                &(_, y) => {
                    dom.min = min;
                    *dom.intervals.get_mut(0) = (min, y);
                    break;
                }
            }
        }
    }

    fn get_min(&self) -> int {
        self.dom.borrow().min
    }

    fn set_max(&self, max: int) {
        let mut dom = self.dom.borrow_mut();
        if max > dom.max { return; }
        if max < dom.min { return; } // TODO failure via conditions
        loop {
            match dom.intervals.last().unwrap() {
                &(_, y) if max > y => { dom.max = y; break; },
                &(x, _) if max < x => { dom.intervals.pop(); },
                &(x, _) => {
                    dom.max = max;
                    *dom.intervals.mut_last().unwrap() = (x, max);
                    break
                }
            }
        }
    }

    fn get_max(&self) -> int {
        self.dom.borrow().max
    }

    fn remove(&self, val: int) {
        let mut dom = self.dom.borrow_mut();
        if val > dom.max || val < dom.min { return; }
        let mut down = 0;
        let mut up = dom.intervals.len();
        let mut test;
        loop {
            test = down + (up - down) / 2;
            match dom.intervals.get(test) {
                &(x, _) if val < x => {
                    if test > down {
                        up = test;
                    } else {
                        break;
                    }
                },
                &(_, y) if val > y => {
                    if test < up - 1 {
                        down = test + 1;
                    } else {
                        break;
                    }
                },
                &(x, y) if val == x && val == y => {
                    dom.intervals.remove(test);
                    break;
                },
                &(x, y) if val == x => {
                    *dom.intervals.get_mut(test) = (x + 1, y);
                    break;
                },
                &(x, y) if val == y => {
                    *dom.intervals.get_mut(test) = (x, y - 1);
                    break;
                },
                &(x, y) => {
                    *dom.intervals.get_mut(test) = (x, val - 1);
                    dom.intervals.insert(test + 1, (val + 1, y));
                    break;
                }
            }
        }
        if test == 0 {
            match dom.intervals.get(test) {
                &(x, _) => dom.min = x
            }
        } else if test == dom.intervals.len() - 1 {
            match dom.intervals.get(test) {
                &(_, y) => dom.max = y
            }
        }
    }
}

impl fmt::Show for Domain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dom = self.dom.borrow();
        let mut s = format!("({}, {}) [", dom.min, dom.max);
        for &(min, max) in dom.intervals.iter() {
            s = s + min.to_str() + ".." + max.to_str() + ", ";
        }
        return write!(f, "{}]", s);
    }
}

impl Var {
    pub fn new(model: Rc<Mod>, min: int, max: int, name: &str) -> Rc<FDVar> {
        assert!(min <= max);
        let id = model.vars.borrow().len();
        let v = Rc::new(FDVar {
            model: model.downgrade(),
            id: id,
            name: name.to_string(),
            dom: Domain::new(min, max)
        });
        model.add_var(v.clone());
        v
    }
}

impl FDVar {
    pub fn min(&self) -> int {
        self.dom.get_min()
    }

    pub fn max(&self) -> int {
        self.dom.get_max()
    }

    fn set_min(&self, v: int) -> Vec<uint> {
        if v > self.min() {
            self.dom.set_min(v);
            if self.is_instanciated() {
                self.model.upgrade().unwrap().get_waiting(self.id, Min)
                    // + self.waitingOnIns
            } else {
                self.model.upgrade().unwrap().get_waiting(self.id, Min)
            }
        } else {
            vec![]
        }
    }

    fn set_max(&self, v: int) -> Vec<uint> {
        if v < self.max() {
            self.dom.set_max(v);
            if self.is_instanciated() {
                // self.waitingOnMax + self.waitingOnIns
                self.model.upgrade().unwrap().get_waiting(self.id, Max)
            } else {
                self.model.upgrade().unwrap().get_waiting(self.id, Max)
            }
        } else {
            vec![]
        }
    }

    fn is_instanciated(&self) -> bool {
        self.min() == self.max()
    }
}

impl fmt::Show for FDVar {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} ({})", self.name, self.dom)
    }
}

pub struct LtXYx : Prop {
    x: uint,
    y: uint
}

impl LtXYx {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYx { model: model.downgrade(), id: id, x: x.id, y: y.id };
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }
}

impl Propagator for LtXYx {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.y, Max)]
    }

    fn propagate(&self) -> Vec<uint> {
        let model = self.model.upgrade().unwrap();
        let mut vars = model.vars.borrow_mut();
        if vars.get(self.x).max() < vars.get(self.y).min() {
            // entailed
            self.unregister();
            vec![]
        } else if vars.get(self.x).max() > vars.get(self.y).max() - 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let max = vars.get(self.y).max() - 1;
            vars.get(self.x).set_max(max)
        } else {
            vec![]
        }
    }
}

pub struct LtXYy : Prop {
    x: uint,
    y: uint
}

impl LtXYy {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYy { model: model.downgrade(), id: id, x: x.id, y: y.id };
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }
}

impl Propagator for LtXYy {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.x, Min)]
    }

    fn propagate(&self) -> Vec<uint> {
        let model = self.model.upgrade().unwrap();
        let mut vars = model.vars.borrow_mut();
        if vars.get(self.x).max() < vars.get(self.y).min() {
            // entailed
            self.unregister();
            vec![]
        } else if vars.get(self.y).min() < vars.get(self.x).min() + 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let min = vars.get(self.x).min() + 1;
            vars.get(self.y).set_min(min)
        } else {
            vec![]
        }
    }
}

#[cfg(test)]
mod tests;
<commit_msg>removing one layer of indirection<commit_after>#![desc = "Constraint Satisfaction in Rust"]
#![license = "MIT"]
#![crate_id = "csar#0.2"]
#![crate_type = "lib"]

#![feature(struct_inherit)]

use std::fmt;
use std::cell::RefCell;
use std::collections::hashmap::HashMap;
use std::rc::{Rc,Weak};

pub struct Mod {
    vars: RefCell<Vec<Rc<FDVar>>>,
    propagators: RefCell<Vec<Rc<Box<Propagator>>>>,
    waiting: RefCell<HashMap<(uint, Event), Vec<uint>>>
}

// cannot use type Model = Rc<Mod> since that would forbid using impl Model
pub struct Model;

/// Representation of finite domains as a list of intervals, maintaining
/// min and max for easy/quick access
#[deriving(Clone)]
struct Dom {
    min: int,
    max: int,
    intervals: Vec<(int, int)>
}

/// Runtime checked mutability with borrowing
#[deriving(Clone)]
struct Domain {
    dom: RefCell<Dom>
}

trait Propagator {
    fn id(&self) -> uint;
    fn model(&self) -> Weak<Mod>;

    fn events(&self) -> Vec<(uint, Event)>;
    fn propagate(&self) -> Vec<uint>;

    fn register(&self) {
        for &(var, event) in self.events().iter() {
            self.model().upgrade().unwrap().add_waiting(var, event, self.id());
        }
    }

    fn unregister(&self) {
        for &(var, event) in self.events().iter() {
            self.model().upgrade().unwrap().del_waiting(var, event, self.id());
        }
    }
}

pub virtual struct Prop {
    id: uint,
    model: Weak<Mod>
}

pub struct Var;

#[deriving(Clone)]
pub struct FDVar {
    model: Weak<Mod>,
    id: uint,
    name: String,
    dom: Domain
}

#[deriving(Show,Hash,Eq,PartialEq)]
pub enum Event {
    Min,
    Max,
    Ins
}

#[allow(dead_code)]
impl Model {
    fn new() -> Rc<Mod> {
        Rc::new(Mod {
            vars: RefCell::new(Vec::new()),
            propagators: RefCell::new(Vec::new()),
            waiting: RefCell::new(HashMap::new())
        })
    }
}

impl Mod {
    fn add_var(&self, var: Rc<FDVar>) {
        self.vars.borrow_mut().push(var);
    }

    fn add_prop(&self, prop: Rc<Box<Propagator>>) {
        self.propagators.borrow_mut().push(prop);
    }

    fn add_waiting(&self, var: uint, event: Event, propagator: uint) {
        let mut waiting = self.waiting.borrow_mut();
        if waiting.contains_key(&(var, event)) {
            waiting.get_mut(&(var, event)).push(propagator);
        } else {
            waiting.insert((var, event), vec![propagator]);
        }
    }

    fn del_waiting(&self, var: uint, event: Event, propagator: uint) {
        self.waiting.borrow_mut().get_mut(&(var, event)).remove(propagator);
    }

    fn get_waiting(&self, var: uint, event: Event) -> Vec<uint> {
        let waiting = self.waiting.borrow();
        match waiting.find_copy(&(var, event)) {
            Some(vec) => vec,
            None => Vec::new()
        }
    }
}

#[allow(dead_code)]
impl Domain {
    /// Domain created with initial bounds
    fn new(min: int, max: int) -> Domain {
        Domain {
            dom: RefCell::new(Dom {
                     min: min,
                     max: max,
                     intervals: vec![(min, max)]
                 })
        }
    }

    fn set_min(&self, min: int) {
        let mut dom = self.dom.borrow_mut();
        if min < dom.min { return; }
        if min > dom.max { return; } // TODO failure via conditions
        loop {
            match dom.intervals.get(0) {
                // note that the breaks are for the loop, not the matching
                &(x, _) if min < x => { dom.min = x; break; },
                &(_, y) if min > y => { dom.intervals.shift(); },
                &(_, y) => {
                    dom.min = min;
                    *dom.intervals.get_mut(0) = (min, y);
                    break;
                }
            }
        }
    }

    fn get_min(&self) -> int {
        self.dom.borrow().min
    }

    fn set_max(&self, max: int) {
        let mut dom = self.dom.borrow_mut();
        if max > dom.max { return; }
        if max < dom.min { return; } // TODO failure via conditions
        loop {
            match dom.intervals.last().unwrap() {
                &(_, y) if max > y => { dom.max = y; break; },
                &(x, _) if max < x => { dom.intervals.pop(); },
                &(x, _) => {
                    dom.max = max;
                    *dom.intervals.mut_last().unwrap() = (x, max);
                    break
                }
            }
        }
    }

    fn get_max(&self) -> int {
        self.dom.borrow().max
    }

    fn remove(&self, val: int) {
        let mut dom = self.dom.borrow_mut();
        if val > dom.max || val < dom.min { return; }
        let mut down = 0;
        let mut up = dom.intervals.len();
        let mut test;
        loop {
            test = down + (up - down) / 2;
            match dom.intervals.get(test) {
                &(x, _) if val < x => {
                    if test > down {
                        up = test;
                    } else {
                        break;
                    }
                },
                &(_, y) if val > y => {
                    if test < up - 1 {
                        down = test + 1;
                    } else {
                        break;
                    }
                },
                &(x, y) if val == x && val == y => {
                    dom.intervals.remove(test);
                    break;
                },
                &(x, y) if val == x => {
                    *dom.intervals.get_mut(test) = (x + 1, y);
                    break;
                },
                &(x, y) if val == y => {
                    *dom.intervals.get_mut(test) = (x, y - 1);
                    break;
                },
                &(x, y) => {
                    *dom.intervals.get_mut(test) = (x, val - 1);
                    dom.intervals.insert(test + 1, (val + 1, y));
                    break;
                }
            }
        }
        if test == 0 {
            match dom.intervals.get(test) {
                &(x, _) => dom.min = x
            }
        } else if test == dom.intervals.len() - 1 {
            match dom.intervals.get(test) {
                &(_, y) => dom.max = y
            }
        }
    }
}

impl fmt::Show for Domain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dom = self.dom.borrow();
        let mut s = format!("({}, {}) [", dom.min, dom.max);
        for &(min, max) in dom.intervals.iter() {
            s = s + min.to_str() + ".." + max.to_str() + ", ";
        }
        return write!(f, "{}]", s);
    }
}

impl Var {
    pub fn new(model: Rc<Mod>, min: int, max: int, name: &str) -> Rc<FDVar> {
        assert!(min <= max);
        let id = model.vars.borrow().len();
        let v = Rc::new(FDVar {
            model: model.downgrade(),
            id: id,
            name: name.to_string(),
            dom: Domain::new(min, max)
        });
        model.add_var(v.clone());
        v
    }
}

impl FDVar {
    pub fn min(&self) -> int {
        self.dom.get_min()
    }

    pub fn max(&self) -> int {
        self.dom.get_max()
    }

    fn set_min(&self, v: int) -> Vec<uint> {
        if v > self.min() {
            self.dom.set_min(v);
            if self.is_instanciated() {
                self.model.upgrade().unwrap().get_waiting(self.id, Min)
                    // + self.waitingOnIns
            } else {
                self.model.upgrade().unwrap().get_waiting(self.id, Min)
            }
        } else {
            vec![]
        }
    }

    fn set_max(&self, v: int) -> Vec<uint> {
        if v < self.max() {
            self.dom.set_max(v);
            if self.is_instanciated() {
                // self.waitingOnMax + self.waitingOnIns
                self.model.upgrade().unwrap().get_waiting(self.id, Max)
            } else {
                self.model.upgrade().unwrap().get_waiting(self.id, Max)
            }
        } else {
            vec![]
        }
    }

    fn is_instanciated(&self) -> bool {
        self.min() == self.max()
    }
}

impl fmt::Show for FDVar {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} ({})", self.name, self.dom)
    }
}

pub struct LtXYx : Prop {
    x: Rc<FDVar>,
    y: Rc<FDVar>
}

impl LtXYx {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYx { model: model.downgrade(), id: id, x: x, y: y };
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }
}

impl Propagator for LtXYx {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.y.id, Max)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x.max() < self.y.min() {
            // entailed
            self.unregister();
            vec![]
        } else if self.x.max() > self.y.max() - 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let max = self.y.max() - 1;
            self.x.set_max(max)
        } else {
            vec![]
        }
    }
}

pub struct LtXYy : Prop {
    x: Rc<FDVar>,
    y: Rc<FDVar>
}

impl LtXYy {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYy { model: model.downgrade(), id: id, x: x, y: y };
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }
}

impl Propagator for LtXYy {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.x.id, Min)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x.max() < self.y.min() {
            // entailed
            self.unregister();
            vec![]
        } else if self.y.min() < self.x.min() + 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let min = self.x.min() + 1;
            self.y.set_min(min)
        } else {
            vec![]
        }
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>use std::io;
use std::fmt::Display;
//use std::time::SystemTime;
//use std::thread::Thread;
//use std::sync::Mutex;

pub mod sensor_data;
pub mod circular_buffer;
pub mod json_display;
pub mod sensors;
pub mod average;
pub mod historic;
pub mod server;

use sensor_data::SensorData;
use circular_buffer::CircularBuffer;
use json_display::JsonDisplay;
use historic::Historic;
use server::Server;

/* // The expected way I want to write my for loop iteration (no more need to call an explicit constructor)
 * // but currently, IntoIterator didn't compile
fn print<T: Display>(cb : &CircularBuffer<T>) {
    println!("=================================================");
    for data in CircularBufferIterator::new(&cb) {
        println!("{}", data);
    }
}
*/

fn print<T: Display + JsonDisplay>(cb : &CircularBuffer<T>) {
    println!("=================================================");
    for data in cb {
        println!("{}", data);
    }
}

fn write_json<T: Display + JsonDisplay>(cb : &CircularBuffer<T>, w: &mut io::Write) {
    let _ = w.write(b"[");
    let _ = cb.write_json_chunk(w);
    let _ = w.write(b"]\n");
}

enum QueuesIndex {
	MINUTE = 0,
	HOUR,
	DAYS,
}

fn main() {
    // array of historic queues of MINUTE, HOUR, DAYS
    let mut historic_queues = [ Historic::<SensorData>::new(32, 24), Historic::<SensorData>::new(128, 120), Historic::<SensorData>::new(9192, 9192)];
    println!("Enter loop");
    loop {
		historic_queues[QueuesIndex::MINUTE as usize].add(SensorData::create());
		println!("nbElements (MINUTE) = {}\tnbElements (HOUR) = {}\tnbElements (DAYS) = {}\n",
		historic_queues[QueuesIndex::MINUTE as usize].get_nb_items(),
        historic_queues[QueuesIndex::HOUR as usize].get_nb_items(),
        historic_queues[QueuesIndex::DAYS as usize].get_nb_items()
        );
        Historic::<SensorData>::reduce(& mut historic_queues);

        // treatSocket(sockfd, historicQueues, QUEUE_NBELEMENTS);
    }
}

#[test]
fn test_circ_buff() {
    let mut circ_buf = CircularBuffer::<SensorData>::new(5);
    circ_buf.put_item(SensorData::new(SystemTime::now(), 1.0, 11, 12, 13));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 2.0, 21, 22, 23));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 3.0, 31, 32, 33));

    assert_eq!(circ_buf.get_nb_items(),3);

    print(&circ_buf);

    circ_buf.put_item(SensorData::new(SystemTime::now(), 4.0, 41, 42, 43));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 5.0, 51, 52, 53));

    assert_eq!(circ_buf.get_nb_items(),5);

    print(&circ_buf);

    // Theses variables data5 and data6 should be refused, because the circularbuffer is full
    circ_buf.put_item(SensorData::new(SystemTime::now(), 6.0, 61, 62, 63));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 7.0, 71, 72, 73));

    assert_eq!(circ_buf.get_nb_items(),5);

    print(&circ_buf);

    match circ_buf.get_item() {
        Some(data0bis_unwrap) =>  {
            println!("data0bis = {}", data0bis_unwrap);
            assert_eq!(data0bis_unwrap.get_bmp280_pressure(),1.0);
            assert_eq!(data0bis_unwrap.get_bmp280_temperature(),11);
            assert_eq!(data0bis_unwrap.get_htu21_temperature(),12);
            assert_eq!(data0bis_unwrap.get_htu21_humidity(),13);
        },
        None => println!("No data0bis")
    }

    // This method will fail without the i2c devices BMP280 and hut21 on the system
    // circ_buf.put_item(SensorData::create());
    // print(&circ_buf);

    write_json(&circ_buf, &mut io::stdout());

    /*
    assert!(Duration::from_secs(1) != Duration::from_secs(0));
    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
               Duration::from_secs(3));
    assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
               Duration::new(4, 10 * 1_000_000));
    assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
    */
}
<commit_msg>Threaded server with Hello answer<commit_after>use std::io;
use std::fmt::Display;
//use std::time::SystemTime;
//use std::thread::Thread;
//use std::sync::Mutex;

pub mod sensor_data;
pub mod circular_buffer;
pub mod json_display;
pub mod sensors;
pub mod average;
pub mod historic;
pub mod server;

use sensor_data::SensorData;
use circular_buffer::CircularBuffer;
use json_display::JsonDisplay;
use historic::Historic;
use server::Server;

/* // The expected way I want to write my for loop iteration (no more need to call an explicit constructor)
 * // but currently, IntoIterator didn't compile
fn print<T: Display>(cb : &CircularBuffer<T>) {
    println!("=================================================");
    for data in CircularBufferIterator::new(&cb) {
        println!("{}", data);
    }
}
*/

fn print<T: Display + JsonDisplay>(cb : &CircularBuffer<T>) {
    println!("=================================================");
    for data in cb {
        println!("{}", data);
    }
}

fn write_json<T: Display + JsonDisplay>(cb : &CircularBuffer<T>, w: &mut io::Write) {
    let _ = w.write(b"[");
    let _ = cb.write_json_chunk(w);
    let _ = w.write(b"]\n");
}

enum QueuesIndex {
	MINUTE = 0,
	HOUR,
	DAYS,
}

fn main() {
    // array of historic queues of MINUTE, HOUR, DAYS
    let mut historic_queues = [ Historic::<SensorData>::new(32, 24), Historic::<SensorData>::new(128, 120), Historic::<SensorData>::new(9192, 9192)];
    Server::create_server_thread("mySocket");
    println!("Enter loop");
    loop {
		historic_queues[QueuesIndex::MINUTE as usize].add(SensorData::create());
		println!("nbElements (MINUTE) = {}\tnbElements (HOUR) = {}\tnbElements (DAYS) = {}\n",
		historic_queues[QueuesIndex::MINUTE as usize].get_nb_items(),
        historic_queues[QueuesIndex::HOUR as usize].get_nb_items(),
        historic_queues[QueuesIndex::DAYS as usize].get_nb_items()
        );
        Historic::<SensorData>::reduce(& mut historic_queues);

        // treatSocket(sockfd, historicQueues, QUEUE_NBELEMENTS);
    }
}

#[test]
fn test_circ_buff() {
    let mut circ_buf = CircularBuffer::<SensorData>::new(5);
    circ_buf.put_item(SensorData::new(SystemTime::now(), 1.0, 11, 12, 13));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 2.0, 21, 22, 23));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 3.0, 31, 32, 33));

    assert_eq!(circ_buf.get_nb_items(),3);

    print(&circ_buf);

    circ_buf.put_item(SensorData::new(SystemTime::now(), 4.0, 41, 42, 43));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 5.0, 51, 52, 53));

    assert_eq!(circ_buf.get_nb_items(),5);

    print(&circ_buf);

    // Theses variables data5 and data6 should be refused, because the circularbuffer is full
    circ_buf.put_item(SensorData::new(SystemTime::now(), 6.0, 61, 62, 63));
    circ_buf.put_item(SensorData::new(SystemTime::now(), 7.0, 71, 72, 73));

    assert_eq!(circ_buf.get_nb_items(),5);

    print(&circ_buf);

    match circ_buf.get_item() {
        Some(data0bis_unwrap) =>  {
            println!("data0bis = {}", data0bis_unwrap);
            assert_eq!(data0bis_unwrap.get_bmp280_pressure(),1.0);
            assert_eq!(data0bis_unwrap.get_bmp280_temperature(),11);
            assert_eq!(data0bis_unwrap.get_htu21_temperature(),12);
            assert_eq!(data0bis_unwrap.get_htu21_humidity(),13);
        },
        None => println!("No data0bis")
    }

    // This method will fail without the i2c devices BMP280 and hut21 on the system
    // circ_buf.put_item(SensorData::create());
    // print(&circ_buf);

    write_json(&circ_buf, &mut io::stdout());

    /*
    assert!(Duration::from_secs(1) != Duration::from_secs(0));
    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
               Duration::from_secs(3));
    assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
               Duration::new(4, 10 * 1_000_000));
    assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
    */
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate iron;
extern crate pretty_bytes;
extern crate chrono;

use std::env;
use std::fs::{self, File};
use std::path::{PathBuf};
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use std::os::unix::ffi::OsStrExt;

use iron::headers;
use iron::{Iron, Request, Response, Set, status};
use pretty_bytes::converter::convert;
use chrono::{DateTime, UTC, TimeZone};

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

    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .default_value("8000")
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let port = matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .unwrap();

    println!("current dir: {:?}", env::current_dir());
    let addr = format!("0.0.0.0:{}", port);
    println!("Server running on: http://{}", addr);

    Iron::new(move |req: &mut Request| {
        println!("Url: {:?}", req.url.path());
        let mut path = root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        match File::open(&path) {
            Ok(f) => {
                let mut resp = Response::with(status::Ok);
                let metadata = f.metadata().unwrap();
                let path_prefix = req.url.path()
                    .into_iter()
                    .filter(|s| !s.is_empty())
                    .collect::<Vec<&str>>();
                if metadata.is_dir() {
                    resp.headers.set(headers::ContentType::html());
                    let mut files = Vec::new();
                    for entry in fs::read_dir(&path).unwrap() {
                        let entry = entry.unwrap();
                        let entry_meta = entry.metadata().unwrap();
                        let file_name = entry.file_name().into_string().unwrap();
                        let file_modified = system_time_to_date_time(entry_meta.modified().unwrap())
                            .format("%Y-%m-%d %H:%M:%S").to_string();
                        let file_size = convert(entry_meta.len() as f64);
                        let mut link = path_prefix.clone();
                        link.push(&file_name);
                        let link = link.join("/");
                        files.push(format!(
                            "
{}	 {}	 <bold>{}</bold>
",
                            link, file_name, file_modified, file_size
                        ));
                    }
                    resp = resp.set(format!("
{}
", files.join("\n")));
                } else {
                    resp.headers.set(headers::ContentDisposition {
                        disposition: headers::DispositionType::Attachment,
                        parameters: vec![headers::DispositionParam::Filename(
                            headers::Charset::Ext("utf-8".to_owned()), // The character set for the bytes of the filename
                            None, // The optional language tag (see `language-tag` crate)
                            path.file_name().unwrap().as_bytes().to_vec() // the actual bytes of the filename
                        )]
                    });
                    resp = resp.set(path);
                    let mime: iron::mime::Mime = "application/octet-stream".parse().unwrap();
                    resp.headers.set(headers::ContentType(mime));
                };
                Ok(resp)
            },
            Err(e) => {
                Ok(Response::with((status::NotFound, e.description().to_string())))
            }
        }
    }).http(addr).unwrap();
}

fn system_time_to_date_time(t: SystemTime) -> DateTime<UTC> {
    let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
        Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
        Err(e) => { // unlikely but should be handled
            let dur = e.duration();
            let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
            if nsec == 0 {
                (-sec, 0)
            } else {
                (-sec - 1, 1_000_000_000 - nsec)
            }
        },
    };
    UTC.timestamp(sec, nsec)
}
<commit_msg>Show parent directory link<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate iron;
extern crate pretty_bytes;
extern crate chrono;

use std::env;
use std::fs::{self, File};
use std::path::{PathBuf};
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use std::os::unix::ffi::OsStrExt;

use iron::headers;
use iron::{Iron, Request, Response, Set, status};
use pretty_bytes::converter::convert;
use chrono::{DateTime, UTC, TimeZone};

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

    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .default_value("8000")
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let port = matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .unwrap();

    println!("current dir: {:?}", env::current_dir());
    let addr = format!("0.0.0.0:{}", port);
    println!("Server running on: http://{}", addr);

    Iron::new(move |req: &mut Request| {
        println!("Url: {:?}", req.url.path());
        let mut path = root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        match File::open(&path) {
            Ok(f) => {
                let mut resp = Response::with(status::Ok);
                let metadata = f.metadata().unwrap();
                let path_prefix = req.url.path()
                    .into_iter()
                    .filter(|s| !s.is_empty())
                    .collect::<Vec<&str>>();
                if metadata.is_dir() {
                    resp.headers.set(headers::ContentType::html());
                    let mut files = Vec::new();
                    if path_prefix.len() > 0 {
                        let mut link = path_prefix.clone();
                        link.pop();
                        files.push(format!(
                            "
{}
",
                            link.join("/"), ".."
                        ));
                    }
                    for entry in fs::read_dir(&path).unwrap() {
                        let entry = entry.unwrap();
                        let entry_meta = entry.metadata().unwrap();
                        let file_name = entry.file_name().into_string().unwrap();
                        let file_modified = system_time_to_date_time(entry_meta.modified().unwrap())
                            .format("%Y-%m-%d %H:%M:%S").to_string();
                        let file_size = convert(entry_meta.len() as f64);
                        let mut link = path_prefix.clone();
                        link.push(&file_name);
                        let link = link.join("/");
                        files.push(format!(
                            "
{}	 {}	 <bold>{}</bold>
",
                            link, file_name, file_modified, file_size
                        ));
                    }
                    resp = resp.set(format!("
{}
", files.join("\n")));
                } else {
                    resp.headers.set(headers::ContentDisposition {
                        disposition: headers::DispositionType::Attachment,
                        parameters: vec![headers::DispositionParam::Filename(
                            headers::Charset::Ext("utf-8".to_owned()), // The character set for the bytes of the filename
                            None, // The optional language tag (see `language-tag` crate)
                            path.file_name().unwrap().as_bytes().to_vec() // the actual bytes of the filename
                        )]
                    });
                    resp = resp.set(path);
                    let mime: iron::mime::Mime = "application/octet-stream".parse().unwrap();
                    resp.headers.set(headers::ContentType(mime));
                };
                Ok(resp)
            },
            Err(e) => {
                Ok(Response::with((status::NotFound, e.description().to_string())))
            }
        }
    }).http(addr).unwrap();
}

fn system_time_to_date_time(t: SystemTime) -> DateTime<UTC> {
    let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
        Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
        Err(e) => { // unlikely but should be handled
            let dur = e.duration();
            let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
            if nsec == 0 {
                (-sec, 0)
            } else {
                (-sec - 1, 1_000_000_000 - nsec)
            }
        },
    };
    UTC.timestamp(sec, nsec)
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(phase)]
#![feature(if_let)]
#[phase(plugin, link)] extern crate log;

extern crate syntax;
extern crate collections;
extern crate core;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::getline;
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search};
#[cfg(not(test))]
use std::io::File;
#[cfg(not(test))]
use std::io::BufferedReader;
#[cfg(not(test))]
use std::str;
#[cfg(not(test))]
use racer::scopes;

pub mod racer;

#[cfg(not(test))]
fn match_fn(m:Match) {
    let (linenum, charnum) = scopes::point_to_coords2(&m.filepath, m.point).unwrap();
    if m.matchstr.as_slice() == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.as_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete() {
    let args = std::os::args();
    match std::from_str::from_str(std::os::args().as_slice()[2].as_slice()) {
        Some(linenum) => {
            // input: linenum, colnum, fname
            let charnum = std::from_str::from_str(std::os::args().as_slice()[3].as_slice()).unwrap();
            let fname = args.as_slice()[4].as_slice();
            let fpath = Path::new(fname);
            let filetxt = BufferedReader::new(File::open(&fpath)).read_to_end().unwrap();
            // print the start-end of the identifier being matched
            let src = str::from_utf8(filetxt.as_slice()).unwrap();
            let line = getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line.as_slice(), charnum);
            println!("PREFIX {},{},{}", start, pos, line.as_slice().slice(start, pos));

            let point = scopes::coords_to_point(src, linenum, charnum);
            for m in racer::complete_from_file(src, &fpath, point) {
                match_fn(m);
            }
        }
        None => {
            // input: a command line string passed in
            let arg = args.as_slice()[2].as_slice();
            let mut it = arg.split_str("::");
            let p : Vec<&str> = it.collect();

            for m in do_file_search(p.as_slice()[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_fn(m);
                } else {
                    for m in do_external_search(p.slice_from(1), &m.filepath, m.point, racer::StartsWith, racer::BothNamespaces) {
                        match_fn(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args_ = std::os::args();
    let args = args_.as_slice();
    let linenum = std::from_str::from_str(args[2].as_slice()).unwrap();
    let charnum = std::from_str::from_str(args[3].as_slice()).unwrap();
    let fname = args[4].as_slice();

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line.as_slice(), charnum);
    println!("PREFIX {},{},{}", start, pos, line.as_slice().slice(start, pos));
}

#[cfg(not(test))]
fn find_definition() {
    let args_ = std::os::args();
    let args = args_.as_slice();
    let linenum = std::from_str::from_str(args[2].as_slice()).unwrap();
    let charnum = std::from_str::from_str(args[3].as_slice()).unwrap();
    let fname = args[4].as_slice();
    let fpath = Path::new(fname);
    let filetxt = BufferedReader::new(File::open(&fpath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();
    let pos = scopes::coords_to_point(src, linenum, charnum);

    racer::find_definition(src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::os::args().as_slice()[0].clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)",program);
    println!("or:    {} prefix linenum charnum fname",program);
}

#[cfg(not(test))]
fn main() {
    if std::os::getenv("RUST_SRC_PATH").is_none() {
        println!("RUST_SRC_PATH environment variable must be set");
        std::os::set_exit_status(1);
        return;
    }

    let args_ = std::os::args();
    let args = args_.as_slice();

    if args.len() == 1 {
        print_usage();
        std::os::set_exit_status(1);
        return;
    }

    let command = args[1].as_slice();
    match command.as_slice() {
        "prefix" => prefix(),
        "complete" => complete(),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        _ => {
            println!("Sorry, I didn't understand command {}", command );
            print_usage();
            std::os::set_exit_status(1);
            return;
        }
    }
}
<commit_msg>FromStr moved to std::str<commit_after>#![feature(macro_rules)]
#![feature(phase)]
#![feature(if_let)]
#[phase(plugin, link)] extern crate log;

extern crate syntax;
extern crate collections;
extern crate core;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::getline;
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search};
#[cfg(not(test))]
use std::io::File;
#[cfg(not(test))]
use std::io::BufferedReader;
#[cfg(not(test))]
use std::str;
#[cfg(not(test))]
use racer::scopes;

pub mod racer;

#[cfg(not(test))]
fn match_fn(m:Match) {
    let (linenum, charnum) = scopes::point_to_coords2(&m.filepath, m.point).unwrap();
    if m.matchstr.as_slice() == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.as_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete() {
    let args = std::os::args();
    match std::str::from_str(std::os::args().as_slice()[2].as_slice()) {
        Some(linenum) => {
            // input: linenum, colnum, fname
            let charnum = std::str::from_str(std::os::args().as_slice()[3].as_slice()).unwrap();
            let fname = args.as_slice()[4].as_slice();
            let fpath = Path::new(fname);
            let filetxt = BufferedReader::new(File::open(&fpath)).read_to_end().unwrap();
            // print the start-end of the identifier being matched
            let src = str::from_utf8(filetxt.as_slice()).unwrap();
            let line = getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line.as_slice(), charnum);
            println!("PREFIX {},{},{}", start, pos, line.as_slice().slice(start, pos));

            let point = scopes::coords_to_point(src, linenum, charnum);
            for m in racer::complete_from_file(src, &fpath, point) {
                match_fn(m);
            }
        }
        None => {
            // input: a command line string passed in
            let arg = args.as_slice()[2].as_slice();
            let mut it = arg.split_str("::");
            let p : Vec<&str> = it.collect();

            for m in do_file_search(p.as_slice()[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_fn(m);
                } else {
                    for m in do_external_search(p.slice_from(1), &m.filepath, m.point, racer::StartsWith, racer::BothNamespaces) {
                        match_fn(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args_ = std::os::args();
    let args = args_.as_slice();
    let linenum = std::str::from_str(args[2].as_slice()).unwrap();
    let charnum = std::str::from_str(args[3].as_slice()).unwrap();
    let fname = args[4].as_slice();

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line.as_slice(), charnum);
    println!("PREFIX {},{},{}", start, pos, line.as_slice().slice(start, pos));
}

#[cfg(not(test))]
fn find_definition() {
    let args_ = std::os::args();
    let args = args_.as_slice();
    let linenum = std::str::from_str(args[2].as_slice()).unwrap();
    let charnum = std::str::from_str(args[3].as_slice()).unwrap();
    let fname = args[4].as_slice();
    let fpath = Path::new(fname);
    let filetxt = BufferedReader::new(File::open(&fpath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();
    let pos = scopes::coords_to_point(src, linenum, charnum);

    racer::find_definition(src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::os::args().as_slice()[0].clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)",program);
    println!("or:    {} prefix linenum charnum fname",program);
}

#[cfg(not(test))]
fn main() {
    if std::os::getenv("RUST_SRC_PATH").is_none() {
        println!("RUST_SRC_PATH environment variable must be set");
        std::os::set_exit_status(1);
        return;
    }

    let args_ = std::os::args();
    let args = args_.as_slice();

    if args.len() == 1 {
        print_usage();
        std::os::set_exit_status(1);
        return;
    }

    let command = args[1].as_slice();
    match command.as_slice() {
        "prefix" => prefix(),
        "complete" => complete(),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        _ => {
            println!("Sorry, I didn't understand command {}", command );
            print_usage();
            std::os::set_exit_status(1);
            return;
        }
    }
}
<|endoftext|>