<commit_before>use bio::io::fastq;
use rust_htslib::bam;
use rust_htslib::bam::Read;
use std::fs;
use std::process::Command;

/// Compare an output file to the expected output and delete the output file.
fn test_output(result: &str, expected: &str) {
    assert!(Command::new("cmp")
        .arg(result)
        .arg(expected)
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    fs::remove_file(result).unwrap();
}

/// Compare two fastq files, ignoring the name lines
/// Reads are sorted by their sequence, which is not 100% robust
/// if mutations/ sequencing errors are considered.
fn compare_fastq(result: &str, expected: &str) {
    let result_reader = fastq::Reader::from_file(result).unwrap();
    let mut result_recs: Vec<fastq::Record> =
        result_reader.records().filter_map(Result::ok).collect();
    result_recs.sort_by_key(|x| x.seq().to_owned());
    let expected_reader = fastq::Reader::from_file(expected).unwrap();
    let mut expected_recs: Vec<fastq::Record> =
        expected_reader.records().filter_map(Result::ok).collect();
    expected_recs.sort_by_key(|x| x.seq().to_owned());

    for (result, expected) in result_recs.iter().zip(expected_recs.iter()) {
        assert_eq!(result.seq(), expected.seq());
        assert_eq!(result.qual(), expected.qual());
    }
}

fn compare_bam(result: &str, expected: &str) {
    let mut result_reader = bam::Reader::from_path(result).unwrap();
    let mut result_recs: Vec<bam::Record> =
        result_reader.records().filter_map(Result::ok).collect();
    result_recs.sort_by_key(|x| x.seq().as_bytes().to_owned());
    let mut expected_reader = bam::Reader::from_path(expected).unwrap();
    let mut expected_recs: Vec<bam::Record> =
        expected_reader.records().filter_map(Result::ok).collect();
    expected_recs.sort_by_key(|x| x.seq().as_bytes().to_owned());
    for (result, expected) in result_recs.iter().zip(expected_recs.iter()) {
        assert_eq!(result.seq().as_bytes(), expected.seq().as_bytes());
        assert_eq!(result.qual(), expected.qual());
    }
}

#[test]
fn fastq_split() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt fastq-split tests/A.fastq tests/B.fastq < tests/test.fastq")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/A.fastq", "tests/expected/A.fastq");
    test_output("tests/B.fastq", "tests/expected/B.fastq");
}

#[test]
fn fastq_filter() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg(
            "target/debug/rbt fastq-filter tests/ids.txt < tests/test.fastq > tests/filtered.fastq"
        )
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/filtered.fastq", "tests/expected/B.fastq");
}

#[test]
fn bam_depth() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt bam-depth tests/test.bam < tests/pos.txt > tests/depth.txt")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/depth.txt", "tests/expected/depth.txt");
}

#[test]
fn vcf_to_txt() {
    assert!(Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-to-txt --genotypes --fmt S --info T X SOMATIC < tests/test.vcf > tests/variant-table.txt")
            .spawn().unwrap().wait().unwrap().success());
    test_output(
        "tests/variant-table.txt",
        "tests/expected/variant-table.txt",
    );
}

#[test]
fn vcf_match() {
    assert!(Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-match -d 50 -l 20 tests/test3.vcf < tests/test2.vcf > tests/matching.bcf")
            .spawn().unwrap().wait().unwrap().success());
    test_output("tests/matching.bcf", "tests/expected/matching.bcf");
}

#[test]
fn vcf_match_same() {
    assert!(Command::new("bash").arg("-c")
                                .arg("target/debug/rbt vcf-match -d 50 -l 20 tests/test4.vcf < tests/test4.vcf > tests/matching-same.bcf")
                                .spawn().unwrap().wait().unwrap().success());
    test_output(
        "tests/matching-same.bcf",
        "tests/expected/matching-same.bcf",
    );
}

#[test]
fn vcf_fix_iupac_alleles() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg(
            "target/debug/rbt vcf-fix-iupac-alleles < tests/test-iupac.vcf > tests/iupac-fixed.bcf"
        )
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/iupac-fixed.bcf", "tests/expected/iupac-fixed.bcf");
}

#[test]
fn vcf_baf() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt vcf-baf < tests/test-freebayes.vcf > tests/baf.bcf")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/baf.bcf", "tests/expected/baf.bcf");
}

#[test]
fn test_vcf_report() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-report tests/ref.fa -v a=tests/report-test.vcf -v b=tests/report-test.vcf -b a:tumor=tests/test-report.bam -b b:tumor=tests/test-report.bam -- tests")
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success()
    );
    let files1 = vec![
        (
            "tests/indexes/index1.html",
            "tests/expected/report/indexes/index1.html",
        ),
        (
            "tests/genes/KRAS1.html",
            "tests/expected/report/genes/KRAS1.html",
        ),
    ];

    let files2 = vec![
        (
            "tests/details/a/KRAS.html",
            "tests/expected/report/details/a/KRAS.html",
        ),
        (
            "tests/details/b/KRAS.html",
            "tests/expected/report/details/b/KRAS.html",
        ),
    ];

    for (result, expected) in files1 {
        // delete line 22 with timestamp and 15 with version
        // this may fail on OS X due to the wrong sed being installed
        assert!(Command::new("bash")
            .arg("-c")
            .arg("sed -i '22d;15d' ".to_owned() + result)
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success());
        test_output(result, expected)
    }
    for (result, expected) in files2 {
        // delete line 29 with timestamp and 22 with version
        // this may fail on OS X due to the wrong sed being installed
        assert!(Command::new("bash")
            .arg("-c")
            .arg("sed -i '29d;22d' ".to_owned() + result)
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success());
        test_output(result, expected)
    }
    fs::remove_dir_all("tests/genes").unwrap();
    fs::remove_dir_all("tests/details").unwrap();
    fs::remove_dir_all("tests/js").unwrap();
    fs::remove_dir_all("tests/css").unwrap();
    fs::remove_dir_all("tests/indexes").unwrap();
    fs::remove_file("tests/index.html").unwrap();
}

#[test]
fn test_collapse_reads_to_fragments_two_cluster() {
    assert!(
        Command::new("bash")
                .arg("-c")
                .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 3 -u --max-umi-dist 0 --max-seq-dist 2 tests/test-consensus.fastq tests/test-consensus.fastq /tmp/test-consensus.1.fastq /tmp/test-consensus.2.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test-consensus.1.fastq",
        "tests/expected/test-consensus.1.fastq",
    );
    compare_fastq(
        "/tmp/test-consensus.2.fastq",
        "tests/expected/test-consensus.2.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_single_cluster() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 3 -u --max-umi-dist 2 --max-seq-dist 2 tests/test-consensus.fastq tests/test-consensus.fastq /tmp/test-consensus_single.1.fastq /tmp/test-consensus_single.2.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test-consensus_single.1.fastq",
        "tests/expected/test-consensus_single.1.fastq",
    );
    compare_fastq(
        "/tmp/test-consensus_single.2.fastq",
        "tests/expected/test-consensus_single.2.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_reads() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 10 --max-umi-dist 0 --max-seq-dist 8 --insert-size 450 --std-dev 50  tests/overlapping-consensus.1.fastq tests/overlapping-consensus.2.fastq /tmp/test_overlapping-consensus.1.fastq /tmp/test_overlapping-consensus.2.fastq /tmp/test_overlapping-consensus.3.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test_overlapping-consensus.1.fastq",
        "tests/expected/test_overlapping-consensus.1.fastq",
    );
    compare_fastq(
        "/tmp/test_overlapping-consensus.2.fastq",
        "tests/expected/test_overlapping-consensus.2.fastq",
    );
    compare_fastq(
        "/tmp/test_overlapping-consensus.3.fastq",
        "tests/expected/test_overlapping-consensus.3.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_from_bam() {
    assert!(
    Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt collapse-reads-to-fragments bam --max-seq-dist 8 tests/overlapping_consensus_marked.bam /tmp/overlapping_consensus_marked.bam")
        .spawn().unwrap().wait().unwrap().success());
    compare_bam(
        "/tmp/overlapping_consensus_marked.bam",
        "tests/expected/overlapping_consensus_marked.bam",
    );
}

#[test]
fn test_vcf_annotate_dgidb() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-annotate-dgidb tests/annotate_dgidb_test.vcf | bcftools view - | wc -l")
            .status().expect("64").success());
}

#[test]
fn test_stats_fasta_file() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt sequence-stats < tests/stats.fasta > /tmp/result.fasta.stats")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());

    test_output(
        "/tmp/result.fasta.stats",
        "tests/expected/result.fasta.stats",
    );
}

#[test]
fn test_stats_fastq_file() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt sequence-stats -q < tests/stats.fastq > /tmp/result.fastq.stats")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());

    test_output(
        "/tmp/result.fastq.stats",
        "tests/expected/result.fastq.stats",
    );
}
<commit_msg>Change test for annotate_dgidb<commit_after>use bio::io::fastq;
use rust_htslib::bam;
use rust_htslib::bam::Read;
use std::fs;
use std::process::Command;

/// Compare an output file to the expected output and delete the output file.
fn test_output(result: &str, expected: &str) {
    assert!(Command::new("cmp")
        .arg(result)
        .arg(expected)
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    fs::remove_file(result).unwrap();
}

/// Compare two fastq files, ignoring the name lines
/// Reads are sorted by their sequence, which is not 100% robust
/// if mutations/ sequencing errors are considered.
fn compare_fastq(result: &str, expected: &str) {
    let result_reader = fastq::Reader::from_file(result).unwrap();
    let mut result_recs: Vec<fastq::Record> =
        result_reader.records().filter_map(Result::ok).collect();
    result_recs.sort_by_key(|x| x.seq().to_owned());
    let expected_reader = fastq::Reader::from_file(expected).unwrap();
    let mut expected_recs: Vec<fastq::Record> =
        expected_reader.records().filter_map(Result::ok).collect();
    expected_recs.sort_by_key(|x| x.seq().to_owned());

    for (result, expected) in result_recs.iter().zip(expected_recs.iter()) {
        assert_eq!(result.seq(), expected.seq());
        assert_eq!(result.qual(), expected.qual());
    }
}

fn compare_bam(result: &str, expected: &str) {
    let mut result_reader = bam::Reader::from_path(result).unwrap();
    let mut result_recs: Vec<bam::Record> =
        result_reader.records().filter_map(Result::ok).collect();
    result_recs.sort_by_key(|x| x.seq().as_bytes().to_owned());
    let mut expected_reader = bam::Reader::from_path(expected).unwrap();
    let mut expected_recs: Vec<bam::Record> =
        expected_reader.records().filter_map(Result::ok).collect();
    expected_recs.sort_by_key(|x| x.seq().as_bytes().to_owned());
    for (result, expected) in result_recs.iter().zip(expected_recs.iter()) {
        assert_eq!(result.seq().as_bytes(), expected.seq().as_bytes());
        assert_eq!(result.qual(), expected.qual());
    }
}

#[test]
fn fastq_split() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt fastq-split tests/A.fastq tests/B.fastq < tests/test.fastq")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/A.fastq", "tests/expected/A.fastq");
    test_output("tests/B.fastq", "tests/expected/B.fastq");
}

#[test]
fn fastq_filter() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg(
            "target/debug/rbt fastq-filter tests/ids.txt < tests/test.fastq > tests/filtered.fastq"
        )
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/filtered.fastq", "tests/expected/B.fastq");
}

#[test]
fn bam_depth() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt bam-depth tests/test.bam < tests/pos.txt > tests/depth.txt")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/depth.txt", "tests/expected/depth.txt");
}

#[test]
fn vcf_to_txt() {
    assert!(Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-to-txt --genotypes --fmt S --info T X SOMATIC < tests/test.vcf > tests/variant-table.txt")
            .spawn().unwrap().wait().unwrap().success());
    test_output(
        "tests/variant-table.txt",
        "tests/expected/variant-table.txt",
    );
}

#[test]
fn vcf_match() {
    assert!(Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-match -d 50 -l 20 tests/test3.vcf < tests/test2.vcf > tests/matching.bcf")
            .spawn().unwrap().wait().unwrap().success());
    test_output("tests/matching.bcf", "tests/expected/matching.bcf");
}

#[test]
fn vcf_match_same() {
    assert!(Command::new("bash").arg("-c")
                                .arg("target/debug/rbt vcf-match -d 50 -l 20 tests/test4.vcf < tests/test4.vcf > tests/matching-same.bcf")
                                .spawn().unwrap().wait().unwrap().success());
    test_output(
        "tests/matching-same.bcf",
        "tests/expected/matching-same.bcf",
    );
}

#[test]
fn vcf_fix_iupac_alleles() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg(
            "target/debug/rbt vcf-fix-iupac-alleles < tests/test-iupac.vcf > tests/iupac-fixed.bcf"
        )
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/iupac-fixed.bcf", "tests/expected/iupac-fixed.bcf");
}

#[test]
fn vcf_baf() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt vcf-baf < tests/test-freebayes.vcf > tests/baf.bcf")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());
    test_output("tests/baf.bcf", "tests/expected/baf.bcf");
}

#[test]
fn test_vcf_report() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-report tests/ref.fa -v a=tests/report-test.vcf -v b=tests/report-test.vcf -b a:tumor=tests/test-report.bam -b b:tumor=tests/test-report.bam -- tests")
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success()
    );
    let files1 = vec![
        (
            "tests/indexes/index1.html",
            "tests/expected/report/indexes/index1.html",
        ),
        (
            "tests/genes/KRAS1.html",
            "tests/expected/report/genes/KRAS1.html",
        ),
    ];

    let files2 = vec![
        (
            "tests/details/a/KRAS.html",
            "tests/expected/report/details/a/KRAS.html",
        ),
        (
            "tests/details/b/KRAS.html",
            "tests/expected/report/details/b/KRAS.html",
        ),
    ];

    for (result, expected) in files1 {
        // delete line 22 with timestamp and 15 with version
        // this may fail on OS X due to the wrong sed being installed
        assert!(Command::new("bash")
            .arg("-c")
            .arg("sed -i '22d;15d' ".to_owned() + result)
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success());
        test_output(result, expected)
    }
    for (result, expected) in files2 {
        // delete line 29 with timestamp and 22 with version
        // this may fail on OS X due to the wrong sed being installed
        assert!(Command::new("bash")
            .arg("-c")
            .arg("sed -i '29d;22d' ".to_owned() + result)
            .spawn()
            .unwrap()
            .wait()
            .unwrap()
            .success());
        test_output(result, expected)
    }
    fs::remove_dir_all("tests/genes").unwrap();
    fs::remove_dir_all("tests/details").unwrap();
    fs::remove_dir_all("tests/js").unwrap();
    fs::remove_dir_all("tests/css").unwrap();
    fs::remove_dir_all("tests/indexes").unwrap();
    fs::remove_file("tests/index.html").unwrap();
}

#[test]
fn test_collapse_reads_to_fragments_two_cluster() {
    assert!(
        Command::new("bash")
                .arg("-c")
                .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 3 -u --max-umi-dist 0 --max-seq-dist 2 tests/test-consensus.fastq tests/test-consensus.fastq /tmp/test-consensus.1.fastq /tmp/test-consensus.2.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test-consensus.1.fastq",
        "tests/expected/test-consensus.1.fastq",
    );
    compare_fastq(
        "/tmp/test-consensus.2.fastq",
        "tests/expected/test-consensus.2.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_single_cluster() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 3 -u --max-umi-dist 2 --max-seq-dist 2 tests/test-consensus.fastq tests/test-consensus.fastq /tmp/test-consensus_single.1.fastq /tmp/test-consensus_single.2.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test-consensus_single.1.fastq",
        "tests/expected/test-consensus_single.1.fastq",
    );
    compare_fastq(
        "/tmp/test-consensus_single.2.fastq",
        "tests/expected/test-consensus_single.2.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_reads() {
    assert!(
        Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt collapse-reads-to-fragments fastq --umi-len 10 --max-umi-dist 0 --max-seq-dist 8 --insert-size 450 --std-dev 50  tests/overlapping-consensus.1.fastq tests/overlapping-consensus.2.fastq /tmp/test_overlapping-consensus.1.fastq /tmp/test_overlapping-consensus.2.fastq /tmp/test_overlapping-consensus.3.fastq")
            .spawn().unwrap().wait().unwrap().success());
    compare_fastq(
        "/tmp/test_overlapping-consensus.1.fastq",
        "tests/expected/test_overlapping-consensus.1.fastq",
    );
    compare_fastq(
        "/tmp/test_overlapping-consensus.2.fastq",
        "tests/expected/test_overlapping-consensus.2.fastq",
    );
    compare_fastq(
        "/tmp/test_overlapping-consensus.3.fastq",
        "tests/expected/test_overlapping-consensus.3.fastq",
    );
}

#[test]
fn test_collapse_reads_to_fragments_from_bam() {
    assert!(
    Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt collapse-reads-to-fragments bam --max-seq-dist 8 tests/overlapping_consensus_marked.bam /tmp/overlapping_consensus_marked.bam")
        .spawn().unwrap().wait().unwrap().success());
    compare_bam(
        "/tmp/overlapping_consensus_marked.bam",
        "tests/expected/overlapping_consensus_marked.bam",
    );
}

#[test]
fn test_vcf_annotate_dgidb() {
    let exec_test = Command::new("bash")
            .arg("-c")
            .arg("target/debug/rbt vcf-annotate-dgidb tests/annotate_dgidb_test.vcf | bcftools view - | wc -l").output()
            .expect("failed to execute process");
    assert!(exec_test.status.success());
    assert_eq!(exec_test.stdout, vec![32, 32, 32, 32, 32, 32, 54, 53, 10]);
}

#[test]
fn test_stats_fasta_file() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt sequence-stats < tests/stats.fasta > /tmp/result.fasta.stats")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());

    test_output(
        "/tmp/result.fasta.stats",
        "tests/expected/result.fasta.stats",
    );
}

#[test]
fn test_stats_fastq_file() {
    assert!(Command::new("bash")
        .arg("-c")
        .arg("target/debug/rbt sequence-stats -q < tests/stats.fastq > /tmp/result.fastq.stats")
        .spawn()
        .unwrap()
        .wait()
        .unwrap()
        .success());

    test_output(
        "/tmp/result.fastq.stats",
        "tests/expected/result.fastq.stats",
    );
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    // TODO
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn main() {
    // just for fun
    let clubs_jack  = "J♣"; // Emacs 'M-x insert-char' followed by BLACK CLUB SUIT
    let hearts_jack = "J♥"; // Emacs 'M-x insert-char' followed by BLACK HEART SUIT
    println!("{}", Black.bold().paint(clubs_jack));
    println!("{}", Red.bold().paint(hearts_jack));
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Uknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<commit_msg>Move comments to keep lines short.<commit_after>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    // TODO
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn main() {
    // just for fun

    // Emacs 'M-x insert-char' followed by BLACK CLUB SUIT
    let clubs_jack  = "J♣";
    // Emacs 'M-x insert-char' followed by BLACK HEART SUIT
    let hearts_jack = "J♥";
    println!("{}", Black.bold().paint(clubs_jack));
    println!("{}", Red.bold().paint(hearts_jack));
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Uknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use super::*;

use std::{fmt, ops::Deref, sync::Arc};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;
type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone, Ord, Eq, Serialize, Deserialize)]
pub enum IVec {
    /// An inlined small value
    Inline(u8, Inner),
    /// A heap-allocated value protected by an Arc
    Remote {
        #[serde(with = "ser")]
        /// The value protected by an Arc
        buf: Arc<[u8]>,
    },
}

impl IVec {
    pub(crate) fn new(v: &[u8]) -> IVec {
        if v.len() <= CUTOFF {
            let sz = v.len() as u8;

            let mut data: Inner = [0u8; CUTOFF];

            unsafe {
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    data.as_mut_ptr(),
                    v.len(),
                );
            }

            IVec::Inline(sz, data)
        } else {
            IVec::Remote { buf: v.into() }
        }
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVec::Inline(..) = self {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(v: &[u8]) -> IVec {
        IVec::new(v)
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if v.len() <= CUTOFF {
            IVec::new(&v)
        } else {
            IVec::Remote {
                // rely on the Arc From specialization
                // for Vec<[T]>, which may improve
                // over time for T's that are Copy
                buf: v.into(),
            }
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        match self {
            IVec::Inline(sz, buf) => &buf[..*sz as usize],
            IVec::Remote { buf } => &*buf,
        }
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(
        &self,
        other: &IVec,
    ) -> Option<std::cmp::Ordering> {
        Some(self.deref().cmp(other.deref()))
    }
}

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self.deref())
    }
}

pub(crate) mod ser {
    use std::sync::Arc;

    use serde::de::{Deserializer, Visitor};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &Arc<[u8]>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&**data)
    }

    struct IVecVisitor;

    impl<'de> Visitor<'de> for IVecVisitor {
        type Value = Arc<[u8]>;

        fn expecting(
            &self,
            formatter: &mut std::fmt::Formatter,
        ) -> std::fmt::Result {
            formatter.write_str("a borrowed byte array")
        }

        #[inline]
        fn visit_borrowed_bytes<E>(
            self,
            v: &'de [u8],
        ) -> Result<Arc<[u8]>, E> {
            Ok(v.into())
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Arc<[u8]>, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(IVecVisitor)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(&[4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Small IVec Deref optimization<commit_after>use super::*;

use std::{fmt, ops::Deref, sync::Arc};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;
type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone, Ord, Eq, Serialize, Deserialize)]
pub enum IVec {
    /// An inlined small value
    Inline(u8, Inner),
    /// A heap-allocated value protected by an Arc
    Remote {
        #[serde(with = "ser")]
        /// The value protected by an Arc
        buf: Arc<[u8]>,
    },
}

impl IVec {
    pub(crate) fn new(v: &[u8]) -> IVec {
        if v.len() <= CUTOFF {
            let sz = v.len() as u8;

            let mut data: Inner = [0u8; CUTOFF];

            unsafe {
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    data.as_mut_ptr(),
                    v.len(),
                );
            }

            IVec::Inline(sz, data)
        } else {
            IVec::Remote { buf: v.into() }
        }
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVec::Inline(..) = self {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(v: &[u8]) -> IVec {
        IVec::new(v)
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if v.len() <= CUTOFF {
            IVec::new(&v)
        } else {
            IVec::Remote {
                // rely on the Arc From specialization
                // for Vec<[T]>, which may improve
                // over time for T's that are Copy
                buf: v.into(),
            }
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        match self {
            IVec::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVec::Remote { buf } => buf.as_ref(),
        }
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(
        &self,
        other: &IVec,
    ) -> Option<std::cmp::Ordering> {
        Some(self.deref().cmp(other.deref()))
    }
}

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self.deref())
    }
}

pub(crate) mod ser {
    use std::sync::Arc;

    use serde::de::{Deserializer, Visitor};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &Arc<[u8]>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&**data)
    }

    struct IVecVisitor;

    impl<'de> Visitor<'de> for IVecVisitor {
        type Value = Arc<[u8]>;

        fn expecting(
            &self,
            formatter: &mut std::fmt::Formatter,
        ) -> std::fmt::Result {
            formatter.write_str("a borrowed byte array")
        }

        #[inline]
        fn visit_borrowed_bytes<E>(
            self,
            v: &'de [u8],
        ) -> Result<Arc<[u8]>, E> {
            Ok(v.into())
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Arc<[u8]>, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(IVecVisitor)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(&[4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<|endoftext|>


<commit_before>use super::{ExecutionStrategy,
            Scope};
use crate::{command::pkg::uninstall_impl,
            error::Result};
use clap::ArgMatches;
use habitat_common::ui::UI;
use habitat_core::package::PackageIdent;
use std::path::Path;

#[derive(Clone, Copy)]
pub enum UninstallMode {
    Single,
    KeepLatest(usize),
}

impl<'a> From<&'a ArgMatches<'a>> for UninstallMode {
    fn from(m: &ArgMatches) -> Self {
        m.value_of("KEEP_LATEST")
         .and_then(|s| s.parse().ok())
         .map(|n| Self::KeepLatest(n))
         .unwrap_or(Self::Single)
    }
}

pub async fn start(ui: &mut UI,
                   ident: &PackageIdent,
                   fs_root_path: &Path,
                   execution_strategy: ExecutionStrategy,
                   mode: UninstallMode,
                   scope: Scope,
                   excludes: &[PackageIdent])
                   -> Result<()> {
    match mode {
        UninstallMode::Single => {
            uninstall_impl::uninstall(ui,
                                      ident,
                                      fs_root_path,
                                      execution_strategy,
                                      scope,
                                      excludes,
                                      false).await
        }
        UninstallMode::KeepLatest(number_latest_to_keep) => {
            uninstall_impl::uninstall_all_but_latest(ui,
                                                     ident,
                                                     number_latest_to_keep,
                                                     fs_root_path,
                                                     execution_strategy,
                                                     scope,
                                                     excludes,
                                                     false).await?;
            Ok(())
        }
    }
}
<commit_msg>Fix clippy<commit_after>use super::{ExecutionStrategy,
            Scope};
use crate::{command::pkg::uninstall_impl,
            error::Result};
use clap::ArgMatches;
use habitat_common::ui::UI;
use habitat_core::package::PackageIdent;
use std::path::Path;

#[derive(Clone, Copy)]
pub enum UninstallMode {
    Single,
    KeepLatest(usize),
}

impl<'a> From<&'a ArgMatches<'a>> for UninstallMode {
    fn from(m: &ArgMatches) -> Self {
        m.value_of("KEEP_LATEST")
         .and_then(|s| s.parse().ok())
         .map(Self::KeepLatest)
         .unwrap_or(Self::Single)
    }
}

pub async fn start(ui: &mut UI,
                   ident: &PackageIdent,
                   fs_root_path: &Path,
                   execution_strategy: ExecutionStrategy,
                   mode: UninstallMode,
                   scope: Scope,
                   excludes: &[PackageIdent])
                   -> Result<()> {
    match mode {
        UninstallMode::Single => {
            uninstall_impl::uninstall(ui,
                                      ident,
                                      fs_root_path,
                                      execution_strategy,
                                      scope,
                                      excludes,
                                      false).await
        }
        UninstallMode::KeepLatest(number_latest_to_keep) => {
            uninstall_impl::uninstall_all_but_latest(ui,
                                                     ident,
                                                     number_latest_to_keep,
                                                     fs_root_path,
                                                     execution_strategy,
                                                     scope,
                                                     excludes,
                                                     false).await?;
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable 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.

use clap::{App, Arg};
use std::result;

use export_docker as docker;

/// A Kubernetes-specific clap:App wrapper
#[derive(Clone)]
pub struct Cli<'a, 'b>
where
    'a: 'b,
{
    pub app: App<'a, 'b>,
}

impl<'a, 'b> Cli<'a, 'b> {
    pub fn new(name: &str, about: &'a str) -> Self {
        let app = docker::Cli::new(name, about).app;

        Cli { app: app }
    }

    pub fn add_all_args(self) -> Self {
        self.add_docker_args()
            .add_output_args()
            .add_runtime_args()
            .add_secret_names_args()
            .add_bind_args()
    }

    pub fn add_docker_args(self) -> Self {
        let cli = docker::Cli { app: self.app };
        let app = cli.add_base_packages_args()
            .add_builder_args()
            .add_tagging_args()
            .add_publishing_args()
            .add_pkg_ident_arg(docker::PkgIdentArgOptions { multiple: false })
            .app
            .arg(
                Arg::with_name("NO_DOCKER_IMAGE")
                    .long("no-docker-image")
                    .short("d")
                    .help(
                        "Disable creation of the Docker image and only create a Kubernetes \
                         manifest",
                    ),
            );

        Cli { app: app }
    }

    pub fn add_output_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("OUTPUT")
                    .value_name("OUTPUT")
                    .long("output")
                    .short("o")
                    .help(
                        "Name of manifest file to create. Pass '-' for stdout (default: -)",
                    ),
            ),
        }
    }

    pub fn add_runtime_args(self) -> Self {
        Cli {
            app: self.app
                .arg(
                    Arg::with_name("COUNT")
                        .value_name("COUNT")
                        .long("count")
                        .validator(valid_natural_number)
                        .help("Count is the number of desired instances"),
                )
                .arg(
                    Arg::with_name("TOPOLOGY")
                        .value_name("TOPOLOGY")
                        .long("topology")
                        .short("t")
                        .possible_values(&["standalone", "leader"])
                        .help(
                            "A topology describes the intended relationship between peers \
                         within a Habitat service group. Specify either standalone or leader \
                         topology (default: standalone)",
                        ),
                )
                .arg(
                    Arg::with_name("GROUP")
                        .value_name("GROUP")
                        .long("service-group")
                        .short("g")
                        .help(
                            "group is a logical grouping of services with the same package and \
                         topology type connected together in a ring (default: default)",
                        ),
                )
                .arg(
                    Arg::with_name("CONFIG")
                        .value_name("CONFIG")
                        .long("config")
                        .short("n")
                        .help(
                            "The path to Habitat configuration file in user.toml format. Habitat \
                            will use it for initial configuration of the service running in a \
                            Kubernetes cluster",
                        ),
                ),
        }
    }

    pub fn add_secret_names_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("RING_SECRET_NAME")
                    .value_name("RING_SECRET_NAME")
                    .long("ring-secret-name")
                    .short("r")
                    .help(
                        "name of the Kubernetes Secret that contains the ring key, which \
                         encrypts the communication between Habitat supervisors",
                    ),
            ),
        }
    }

    pub fn add_bind_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("BIND")
                    .value_name("BIND")
                    .long("bind")
                    .short("b")
                    .multiple(true)
                    .number_of_values(1)
                    .help(
                        "Bind to another service to form a producer/consumer relationship, \
                         specified as name:service:group",
                    ),
            ),
        }
    }
}

fn valid_natural_number(val: String) -> result::Result<(), String> {
    match val.parse::<u32>() {
        Ok(_) => Ok(()),
        Err(_) => Err(format!("{} is not a natural number", val)),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_natural_number() {
        valid_natural_number("99".to_owned()).unwrap();

        for &s in ["x", "", "#####", "0x11", "ab"].iter() {
            assert!(valid_natural_number(s.to_owned()).is_err());
        }
    }
}
<commit_msg>pkg-export-k8s: Add docs to Cli<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable 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.

use clap::{App, Arg};
use std::result;

use export_docker as docker;

/// A Kubernetes-specific clap:App wrapper
///
/// The API here is provided to make it possible to reuse the CLI code of the Kubernetes exporter.
/// The CLI argument addition is divided between multiple methods to allow you to only pick the
/// parts of the CLI that you need.
#[derive(Clone)]
pub struct Cli<'a, 'b>
where
    'a: 'b,
{
    pub app: App<'a, 'b>,
}

impl<'a, 'b> Cli<'a, 'b> {
    /// Create a `Cli`
    ///
    /// # Arguments
    ///
    /// * `name` - The name of the CLI application to show in `--help' output.
    /// * `about` - The long description of the CLi to show in `--help' output.
    pub fn new(name: &str, about: &'a str) -> Self {
        let app = docker::Cli::new(name, about).app;

        Cli { app: app }
    }

    /// Convenient method to add all known arguments to the CLI.
    pub fn add_all_args(self) -> Self {
        self.add_docker_args()
            .add_output_args()
            .add_runtime_args()
            .add_secret_names_args()
            .add_bind_args()
    }

    pub fn add_docker_args(self) -> Self {
        let cli = docker::Cli { app: self.app };
        let app = cli.add_base_packages_args()
            .add_builder_args()
            .add_tagging_args()
            .add_publishing_args()
            .add_pkg_ident_arg(docker::PkgIdentArgOptions { multiple: false })
            .app
            .arg(
                Arg::with_name("NO_DOCKER_IMAGE")
                    .long("no-docker-image")
                    .short("d")
                    .help(
                        "Disable creation of the Docker image and only create a Kubernetes \
                         manifest",
                    ),
            );

        Cli { app: app }
    }

    pub fn add_output_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("OUTPUT")
                    .value_name("OUTPUT")
                    .long("output")
                    .short("o")
                    .help(
                        "Name of manifest file to create. Pass '-' for stdout (default: -)",
                    ),
            ),
        }
    }

    /// Add Habitat (operator) runtime arguments to the CLI.
    pub fn add_runtime_args(self) -> Self {
        Cli {
            app: self.app
                .arg(
                    Arg::with_name("COUNT")
                        .value_name("COUNT")
                        .long("count")
                        .validator(valid_natural_number)
                        .help("Count is the number of desired instances"),
                )
                .arg(
                    Arg::with_name("TOPOLOGY")
                        .value_name("TOPOLOGY")
                        .long("topology")
                        .short("t")
                        .possible_values(&["standalone", "leader"])
                        .help(
                            "A topology describes the intended relationship between peers \
                         within a Habitat service group. Specify either standalone or leader \
                         topology (default: standalone)",
                        ),
                )
                .arg(
                    Arg::with_name("GROUP")
                        .value_name("GROUP")
                        .long("service-group")
                        .short("g")
                        .help(
                            "group is a logical grouping of services with the same package and \
                         topology type connected together in a ring (default: default)",
                        ),
                )
                .arg(
                    Arg::with_name("CONFIG")
                        .value_name("CONFIG")
                        .long("config")
                        .short("n")
                        .help(
                            "The path to Habitat configuration file in user.toml format. Habitat \
                            will use it for initial configuration of the service running in a \
                            Kubernetes cluster",
                        ),
                ),
        }
    }

    pub fn add_secret_names_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("RING_SECRET_NAME")
                    .value_name("RING_SECRET_NAME")
                    .long("ring-secret-name")
                    .short("r")
                    .help(
                        "name of the Kubernetes Secret that contains the ring key, which \
                         encrypts the communication between Habitat supervisors",
                    ),
            ),
        }
    }

    pub fn add_bind_args(self) -> Self {
        Cli {
            app: self.app.arg(
                Arg::with_name("BIND")
                    .value_name("BIND")
                    .long("bind")
                    .short("b")
                    .multiple(true)
                    .number_of_values(1)
                    .help(
                        "Bind to another service to form a producer/consumer relationship, \
                         specified as name:service:group",
                    ),
            ),
        }
    }
}

fn valid_natural_number(val: String) -> result::Result<(), String> {
    match val.parse::<u32>() {
        Ok(_) => Ok(()),
        Err(_) => Err(format!("{} is not a natural number", val)),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_natural_number() {
        valid_natural_number("99".to_owned()).unwrap();

        for &s in ["x", "", "#####", "0x11", "ab"].iter() {
            assert!(valid_natural_number(s.to_owned()).is_err());
        }
    }
}
<|endoftext|>


<commit_before>
enum ConstraintMode{
    Max,
    Crop,
    Pad
}
enum Scaling{
    Down,
    Both,
    Canvas
}
enum AspectHandling{
    CropToRatioWhenSmaller,
    PadToRatioWhenSmaller,
    RevertToOrigin,
}
struct ConstraintParams{
    w: Option<u32>,
    h: Option<u32>,
    scale: Scaling,
    aspect_handling: AspectHandling,
    mode: ConstraintMode
}

//use ieee754::Ieee754;
//extern crate ieee754;

// <meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width, Downlink">
// <link rel=preload
// lazySizes javascript
// Cuzillion

// https://jmperezperez.com/medium-image-progressive-loading-placeholder/
// http://httpwg.org/http-extensions/client-hints.html#the-save-data-hint
// https://developers.google.com/web/updates/tags/clienthints
//
// To verify
// min-w/max-w/min-h/max-h + fit=crop a la imgix https://docs.imgix.com/apis/url/size/min-h

// 1x and 2x are enough. Specifying size on HTML means we must, at least preserve the aspect ratio``
// If crop or pad.
// width/height/max
// width/height/crop - when larger than original - should crop minimally to aspect ratio by default.
// width/height/pad - when larger than original - should pad minimally to aspect ratio.
// aspectforce=crop|pad?
// scale=both|canvas

// when width or height are specified alone, there is no expectation of aspect ratio.

// toosmall=preserveaspect,upscale,expandcanvas

// http://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/

/// When a constraint requires cropping, how should it be selected?
enum CropSelection{
    Center
}
/// When a constraint requires padding, where shall it be added?
enum PaddingLocation{
    Even
}

/// Strategies for single dimension constraints: I.e, Width OR Height, but not both
enum OneConstraintStrategy{
    /// The constraint is an upper bound; the image will never be upscaled,
    /// and downscaling will preserve the original aspect ratio
    Max,
    /// (no use case) The constraint is a lower bound. If the image is smaller than this value, it will be upscaled, preserving the original aspect ratio.
    Min,
    /// (no use case)  If the original image is too small, the canvas will be extended in that one dimension, following the PaddingLocation rules.
    ExactViaCanvas1D,
    /// (no use case) If too small, the canvas will be extended in both directions as required to match both the original aspect ratio and the desired dimension.
    ExactViaCanvas,
    /// (no use case) If too small, the image will be upscaled so that the given dimension is an exact match.
    ExactViaUpscaling,
    /// (no use case) If too small, distort. Otherwise, preserve aspect ratio.
    ExactViaDistortion,
    /// (no use case) The image's aspect ratio will be ignored, and scaled in a single dimension to the given value.
    ExactAlwaysDistort,
    /// (no use case) Don't scale the image; rather, crop or pad it in a single dimension.
    /// always.fit=crop(target).pad(target)
    ExactAlwaysCropOrPad
}

enum StrategyIfLarger2D {
    DownscaleWithin,
    DownscaleCrop,
    DownscaleCropCare,
    DownscalePad,

    Distort
}

enum StrategyIfMismatch {
    DownscaleWithin,
    Crop1D,
    CropThenPad,
    CropCareThenPad,
    CropThenUpscale,
    CropCareThenUpscale,
    Distort
}

enum StrategyIfSmaller2D {
    Pad,
    // Upscaling can bring us into the mismatch zone.
    UpscaleThenPad,
    UpscaleThenCropCare,
    UpscaleThenCrop,
    Distort,
    DistortAspect,
    CropToAspect,
    CropCareToAspect,
    PadToAspect
}

enum ComparisonState {
    Larger2D,
    Smaller2D,
    Mismatch
}
/////////////////////////////////////////////////////////
// Given a ScaleAbove and ScaleBelow which can cause one dimension to match the provided box
// And the other to be larger (or smaller), but with minimal loss of information.
// This can be used to achieve a state where we can reason about aspect ratio changes from
// an initial state of
enum PostScaleState {
    Larger1D,
    Smaller1D,
    Larger1DSmaller1D,
    //The image is either larger2d or smaller2d, and we are not targeting scaling.
    DontCare
}
// After exhausting our acceptable aspect ratio modification strategies,
// We may have (a) success, or (b) partial (or no) progress towards the aspect ratio goal.
// If successful, we should be able to scale the rest of the way IF desired. (say we added padding coming from Larger2D or cropped from Smaller2D). WithinBox and
// When partially successful,
//
// We may 1. Downscale within bounds, Downscale to exact bounds,

// AspectModifier trait
// - provide pixel buffer or rect, desired aspect ratio, and a dimension constraint?
// - get resultant crop and resultant canvas

/// Here we combine a 1 dimensional constraint and a target aspect ratio.
/// We assume that the biggest delta dimension is processed first. I.e, width if the source image has a wider aspect ratio, height if the source image has a higher aspect ratio.
///
enum TargetAndAspect {}

/// Strategies for single dimension constraints: I.e, Width OR Height, but not both
enum Constraint1DAndAspectStrategy {
    /// The constraint is an upper bound; the image will never be upscaled,
/// and downscaling will preserve the original aspect ratio
    Max,
    /// Ensures that at least one dimension is equal to or smaller than the provided box (alt. dimension estimated via aspect ratio). aka. MinimalSupersetNoUspcaling
/// (fits outside box)
    MaxAny,
    /// (no use case) The constraint is a lower bound. If the image is smaller than this value, it will be upscaled, preserving the original aspect ratio.
/// (like maxany (if done twice), fits outside)
    Min,
    /// (like max done twice, fits within box).
    MinAny,
    /// (no use case)  If the original image is too small, the canvas will be extended in that one dimension, following the PaddingLocation rules.
    ExactViaCanvas1D,
    /// (no use case) If too small, the canvas will be extended in both directions as required to match both the original aspect ratio and the desired dimension.
    ExactViaCanvas,
    /// (no use case) If too small, the image will be upscaled so that the given dimension is an exact match.
    ExactViaUpscaling,
    /// (no use case) If too small, distort. Otherwise, preserve aspect ratio.
    ExactViaDistortion,
    /// (no use case) The image's aspect ratio will be ignored, and scaled in a single dimension to the given value.
    ExactAlwaysDistort,
    /// (no use case) Don't scale the image; rather, crop or pad it in a single dimension.
    ExactAlwaysCropOrPad
}

enum ConstraintStrategy {
    Width {
        w: u32,
        strategy: OneConstraintStrategy
    },
    Height {
        h: u32,
        strategy: OneConstraintStrategy
    },
    /// Keep the original aspect ratio. If the image is smaller than both bounds, don't upscale or pad.
    WithinBox {
        w: u32,
        h: u32
    },
}
<commit_msg>spelling: upscaling<commit_after>
enum ConstraintMode{
    Max,
    Crop,
    Pad
}
enum Scaling{
    Down,
    Both,
    Canvas
}
enum AspectHandling{
    CropToRatioWhenSmaller,
    PadToRatioWhenSmaller,
    RevertToOrigin,
}
struct ConstraintParams{
    w: Option<u32>,
    h: Option<u32>,
    scale: Scaling,
    aspect_handling: AspectHandling,
    mode: ConstraintMode
}

//use ieee754::Ieee754;
//extern crate ieee754;

// <meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width, Downlink">
// <link rel=preload
// lazySizes javascript
// Cuzillion

// https://jmperezperez.com/medium-image-progressive-loading-placeholder/
// http://httpwg.org/http-extensions/client-hints.html#the-save-data-hint
// https://developers.google.com/web/updates/tags/clienthints
//
// To verify
// min-w/max-w/min-h/max-h + fit=crop a la imgix https://docs.imgix.com/apis/url/size/min-h

// 1x and 2x are enough. Specifying size on HTML means we must, at least preserve the aspect ratio``
// If crop or pad.
// width/height/max
// width/height/crop - when larger than original - should crop minimally to aspect ratio by default.
// width/height/pad - when larger than original - should pad minimally to aspect ratio.
// aspectforce=crop|pad?
// scale=both|canvas

// when width or height are specified alone, there is no expectation of aspect ratio.

// toosmall=preserveaspect,upscale,expandcanvas

// http://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/

/// When a constraint requires cropping, how should it be selected?
enum CropSelection{
    Center
}
/// When a constraint requires padding, where shall it be added?
enum PaddingLocation{
    Even
}

/// Strategies for single dimension constraints: I.e, Width OR Height, but not both
enum OneConstraintStrategy{
    /// The constraint is an upper bound; the image will never be upscaled,
    /// and downscaling will preserve the original aspect ratio
    Max,
    /// (no use case) The constraint is a lower bound. If the image is smaller than this value, it will be upscaled, preserving the original aspect ratio.
    Min,
    /// (no use case)  If the original image is too small, the canvas will be extended in that one dimension, following the PaddingLocation rules.
    ExactViaCanvas1D,
    /// (no use case) If too small, the canvas will be extended in both directions as required to match both the original aspect ratio and the desired dimension.
    ExactViaCanvas,
    /// (no use case) If too small, the image will be upscaled so that the given dimension is an exact match.
    ExactViaUpscaling,
    /// (no use case) If too small, distort. Otherwise, preserve aspect ratio.
    ExactViaDistortion,
    /// (no use case) The image's aspect ratio will be ignored, and scaled in a single dimension to the given value.
    ExactAlwaysDistort,
    /// (no use case) Don't scale the image; rather, crop or pad it in a single dimension.
    /// always.fit=crop(target).pad(target)
    ExactAlwaysCropOrPad
}

enum StrategyIfLarger2D {
    DownscaleWithin,
    DownscaleCrop,
    DownscaleCropCare,
    DownscalePad,

    Distort
}

enum StrategyIfMismatch {
    DownscaleWithin,
    Crop1D,
    CropThenPad,
    CropCareThenPad,
    CropThenUpscale,
    CropCareThenUpscale,
    Distort
}

enum StrategyIfSmaller2D {
    Pad,
    // Upscaling can bring us into the mismatch zone.
    UpscaleThenPad,
    UpscaleThenCropCare,
    UpscaleThenCrop,
    Distort,
    DistortAspect,
    CropToAspect,
    CropCareToAspect,
    PadToAspect
}

enum ComparisonState {
    Larger2D,
    Smaller2D,
    Mismatch
}
/////////////////////////////////////////////////////////
// Given a ScaleAbove and ScaleBelow which can cause one dimension to match the provided box
// And the other to be larger (or smaller), but with minimal loss of information.
// This can be used to achieve a state where we can reason about aspect ratio changes from
// an initial state of
enum PostScaleState {
    Larger1D,
    Smaller1D,
    Larger1DSmaller1D,
    //The image is either larger2d or smaller2d, and we are not targeting scaling.
    DontCare
}
// After exhausting our acceptable aspect ratio modification strategies,
// We may have (a) success, or (b) partial (or no) progress towards the aspect ratio goal.
// If successful, we should be able to scale the rest of the way IF desired. (say we added padding coming from Larger2D or cropped from Smaller2D). WithinBox and
// When partially successful,
//
// We may 1. Downscale within bounds, Downscale to exact bounds,

// AspectModifier trait
// - provide pixel buffer or rect, desired aspect ratio, and a dimension constraint?
// - get resultant crop and resultant canvas

/// Here we combine a 1 dimensional constraint and a target aspect ratio.
/// We assume that the biggest delta dimension is processed first. I.e, width if the source image has a wider aspect ratio, height if the source image has a higher aspect ratio.
///
enum TargetAndAspect {}

/// Strategies for single dimension constraints: I.e, Width OR Height, but not both
enum Constraint1DAndAspectStrategy {
    /// The constraint is an upper bound; the image will never be upscaled,
/// and downscaling will preserve the original aspect ratio
    Max,
    /// Ensures that at least one dimension is equal to or smaller than the provided box (alt. dimension estimated via aspect ratio). aka. MinimalSupersetNoUpscaling
/// (fits outside box)
    MaxAny,
    /// (no use case) The constraint is a lower bound. If the image is smaller than this value, it will be upscaled, preserving the original aspect ratio.
/// (like maxany (if done twice), fits outside)
    Min,
    /// (like max done twice, fits within box).
    MinAny,
    /// (no use case)  If the original image is too small, the canvas will be extended in that one dimension, following the PaddingLocation rules.
    ExactViaCanvas1D,
    /// (no use case) If too small, the canvas will be extended in both directions as required to match both the original aspect ratio and the desired dimension.
    ExactViaCanvas,
    /// (no use case) If too small, the image will be upscaled so that the given dimension is an exact match.
    ExactViaUpscaling,
    /// (no use case) If too small, distort. Otherwise, preserve aspect ratio.
    ExactViaDistortion,
    /// (no use case) The image's aspect ratio will be ignored, and scaled in a single dimension to the given value.
    ExactAlwaysDistort,
    /// (no use case) Don't scale the image; rather, crop or pad it in a single dimension.
    ExactAlwaysCropOrPad
}

enum ConstraintStrategy {
    Width {
        w: u32,
        strategy: OneConstraintStrategy
    },
    Height {
        h: u32,
        strategy: OneConstraintStrategy
    },
    /// Keep the original aspect ratio. If the image is smaller than both bounds, don't upscale or pad.
    WithinBox {
        w: u32,
        h: u32
    },
}
<|endoftext|>


<commit_before>//! Rustc Diagnostic JSON Output
//!
//! The following data types are copied from [rust-lang/rust](https://github.com/rust-lang/rust/blob/de78655bca47cac8e783dbb563e7e5c25c1fae40/src/libsyntax/json.rs)

#[derive(Serialize, Deserialize, Debug)]
pub struct Diagnostic {
    /// The primary error message.
    pub message: String,
    pub code: Option<DiagnosticCode>,
    /// "error: internal compiler error", "error", "warning", "note", "help".
    pub level: String,
    pub spans: Vec<DiagnosticSpan>,
    /// Associated diagnostic messages.
    pub children: Vec<Diagnostic>,
    /// The message as rustc would render it. Currently this is only
    /// `Some` for "suggestions", but eventually it will include all
    /// snippets.
    pub rendered: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticSpan {
    pub file_name: String,
    pub byte_start: usize,
    pub byte_end: usize,
    /// 1-based.
    pub line_start: usize,
    pub line_end: usize,
    /// 1-based, character offset.
    pub column_start: usize,
    pub column_end: usize,
    /// Is this a "primary" span -- meaning the point, or one of the points,
    /// where the error occurred?
    pub is_primary: bool,
    /// Source text from the start of line_start to the end of line_end.
    pub text: Vec<DiagnosticSpanLine>,
    /// Label that should be placed at this location (if any)
    pub label: Option<String>,
    /// If we are suggesting a replacement, this will contain text
    /// that should be sliced in atop this span. You may prefer to
    /// load the fully rendered version from the parent `Diagnostic`,
    /// however.
    pub suggested_replacement: Option<String>,
    /// Macro invocations that created the code at this span, if any.
    #[serde(bound="")]
    pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticSpanLine {
    pub text: String,

    /// 1-based, character offset in self.text.
    pub highlight_start: usize,
    pub highlight_end: usize,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticSpanMacroExpansion {
    /// span where macro was applied to generate this code; note that
    /// this may itself derive from a macro (if
    /// `span.expansion.is_some()`)
    pub span: DiagnosticSpan,

    /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
    pub macro_decl_name: String,

    /// span where macro was defined (if known)
    pub def_site_span: Option<DiagnosticSpan>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticCode {
    /// The code itself.
    pub code: String,
    /// An explanation for the code.
    pub explanation: Option<String>,
}
<commit_msg>Limit public parts of diagnostic structs to actually used parts<commit_after>//! Rustc Diagnostic JSON Output
//!
//! The following data types are copied from [rust-lang/rust](https://github.com/rust-lang/rust/blob/de78655bca47cac8e783dbb563e7e5c25c1fae40/src/libsyntax/json.rs)

#[derive(Serialize, Deserialize, Debug)]
pub struct Diagnostic {
    /// The primary error message.
    pub message: String,
    code: Option<DiagnosticCode>,
    /// "error: internal compiler error", "error", "warning", "note", "help".
    level: String,
    pub spans: Vec<DiagnosticSpan>,
    /// Associated diagnostic messages.
    pub children: Vec<Diagnostic>,
    /// The message as rustc would render it. Currently this is only
    /// `Some` for "suggestions", but eventually it will include all
    /// snippets.
    rendered: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticSpan {
    pub file_name: String,
    byte_start: u32,
    byte_end: u32,
    /// 1-based.
    pub line_start: usize,
    pub line_end: usize,
    /// 1-based, character offset.
    pub column_start: usize,
    pub column_end: usize,
    /// Is this a "primary" span -- meaning the point, or one of the points,
    /// where the error occurred?
    is_primary: bool,
    /// Source text from the start of line_start to the end of line_end.
    pub text: Vec<DiagnosticSpanLine>,
    /// Label that should be placed at this location (if any)
    label: Option<String>,
    /// If we are suggesting a replacement, this will contain text
    /// that should be sliced in atop this span. You may prefer to
    /// load the fully rendered version from the parent `Diagnostic`,
    /// however.
    pub suggested_replacement: Option<String>,
    /// Macro invocations that created the code at this span, if any.
    expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct DiagnosticSpanLine {
    pub text: String,

    /// 1-based, character offset in self.text.
    pub highlight_start: usize,

    pub highlight_end: usize,
}

#[derive(Serialize, Deserialize, Debug)]
struct DiagnosticSpanMacroExpansion {
    /// span where macro was applied to generate this code; note that
    /// this may itself derive from a macro (if
    /// `span.expansion.is_some()`)
    span: DiagnosticSpan,

    /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
    macro_decl_name: String,

    /// span where macro was defined (if known)
    def_site_span: Option<DiagnosticSpan>,
}

#[derive(Serialize, Deserialize, Debug)]
struct DiagnosticCode {
    /// The code itself.
    code: String,
    /// An explanation for the code.
    explanation: Option<String>,
}
<|endoftext|>