<commit_before>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, SubCommand, ErrorKind, Arg};

static HELP: &'static str = "clap-test v1.4.8
Kevin K. <kbknapp@gmail.com>
tests clap library

USAGE:
    clap-test [FLAGS] [OPTIONS] [ARGS] [SUBCOMMAND]

FLAGS:
    -f, --flag       tests flags
    -F               tests flags with exclusions
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -O, --Option <option3>           specific vals [values: fast, slow]
        --long-option-2 <option2>    tests long options with exclusions
        --maxvals3 <maxvals>...      Tests 3 max vals
        --minvals2 <minvals>...      Tests 2 min vals
        --multvals <one> <two>       Tests mutliple values, not mult occs
        --multvalsmo <one> <two>     Tests mutliple values, and mult occs
    -o, --option <opt>...            tests options

ARGS:
    <positional>        tests positionals
    <positional2>       tests positionals with exclusions
    <positional3>...    tests specific values [values: vi, emacs]

SUBCOMMANDS:
    help      Prints this message or the help of the given subcommand(s)
    subcmd    tests subcommands";

static AFTER_HELP: &'static str = "some text that comes before the help

clap-test v1.4.8
tests clap library

USAGE:
    clap-test

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

some text that comes after the help";

static SC_HELP: &'static str = "subcmd 0.1
Kevin K. <kbknapp@gmail.com>
tests subcommands

USAGE:
    subcmd [FLAGS] [OPTIONS] [--] [scpositional]

FLAGS:
    -f, --flag    tests flags

OPTIONS:
    -o, --option <scoption>...    tests options

ARGS:
    <scpositional>    tests positionals";

static MULTI_SC_HELP: &'static str = "ctest-subcmd-multi 0.1
Kevin K. <kbknapp@gmail.com>
tests subcommands

USAGE:
    ctest subcmd multi [FLAGS] [OPTIONS]

FLAGS:
    -f, --flag       tests flags
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -o, --option <scoption>...    tests options";

static ISSUE_626_CUTOFF: &'static str = "ctest 0.1

USAGE:
    ctest [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --cafe <FILE>    A coffeehouse, coffee shop, or café is an
                         establishment which primarily serves hot
                         coffee, related coffee beverages (e.g.,
                         café latte, cappuccino, espresso), tea,
                         and other hot beverages. Some
                         coffeehouses also serve cold beverages
                         such as iced coffee and iced tea. Many
                         cafés also serve some type of food, such
                         as light snacks, muffins, or pastries.";

static ISSUE_626_PANIC: &'static str = "ctest 0.1

USAGE:
    ctest [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --cafe <FILE>
            La culture du café est très développée
            dans de nombreux pays à climat chaud
            d\'Amérique, d\'Afrique et d\'Asie,
            dans des plantations qui sont
            cultivées pour les marchés
            d\'exportation. Le café est souvent
            une contribution majeure aux
            exportations des régions productrices.";

#[test]
fn help_short() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "-h"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn help_long() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "--help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn help_no_subcommand() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
}

#[test]
fn help_subcommand() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .subcommand(SubCommand::with_name("test")
            .about("tests things")
            .arg_from_usage("-v --verbose 'with verbosity'"))
        .get_matches_from_safe(vec!["myprog", "help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_short_help() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_long_help() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_help_rev() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn complex_help_output() {
    test::check_help(test::complex_app(), HELP);
}

#[test]
fn after_and_before_help_output() {
    let app = App::new("clap-test")
        .version("v1.4.8")
        .about("tests clap library")
        .before_help("some text that comes before the help")
        .after_help("some text that comes after the help");
    test::check_help(app, AFTER_HELP);
}

#[test]
fn multi_level_sc_help() {
    let app = App::new("ctest")
        .subcommand(SubCommand::with_name("subcmd")
            .subcommand(SubCommand::with_name("multi")
                .about("tests subcommands")
                .author("Kevin K. <kbknapp@gmail.com>")
                .version("0.1")
                .args_from_usage("
                    -f, --flag                    'tests flags'
                    -o, --option [scoption]...    'tests options'
                ")));
    test::check_err_output(app, "ctest help subcmd multi", MULTI_SC_HELP, false);
}

#[test]
fn no_wrap_help() {
    let app = App::new("ctest")
        .set_term_width(0)
        .help(MULTI_SC_HELP);
    test::check_err_output(app, "ctest --help", MULTI_SC_HELP, false);
}

#[test]
fn complex_subcommand_help_output() {
    let mut a = test::complex_app();
    let _ = a.get_matches_from_safe_borrow(vec![""]);
    let sc = a.p.subcommands.iter().filter(|s| s.p.meta.name == "subcmd").next().unwrap();
    // Now we check the output of print_help()
    let mut help = vec![];
    sc.write_help(&mut help).ok().expect("failed to print help");
    assert_eq!(&*String::from_utf8(help).unwrap(), SC_HELP);
}

#[test]
fn issue_626_unicode_cutoff() {
    let app = App::new("ctest")
        .version("0.1")
        .set_term_width(70)
        .arg(Arg::with_name("cafe")
           .short("c")
           .long("cafe")
           .value_name("FILE")
           .help("A coffeehouse, coffee shop, or café is an establishment \
           which primarily serves hot coffee, related coffee beverages \
           (e.g., café latte, cappuccino, espresso), tea, and other hot \
           beverages. Some coffeehouses also serve cold beverages such as \
           iced coffee and iced tea. Many cafés also serve some type of \
           food, such as light snacks, muffins, or pastries.")
           .takes_value(true));
    test::check_err_output(app, "ctest --help", ISSUE_626_CUTOFF, false);
}

#[test]
fn issue_626_panic() {
    let app = App::new("ctest")
        .version("0.1")
        .set_term_width(52)
        .arg(Arg::with_name("cafe")
           .short("c")
           .long("cafe")
           .value_name("FILE")
           .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
           d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
           Le café est souvent une contribution majeure aux exportations des régions productrices.")
           .takes_value(true));
    test::check_err_output(app, "ctest --help", ISSUE_626_PANIC, false);
}

#[test]
fn issue_626_variable_panic() {
    for i in 10..320 {
        let _ = App::new("ctest")
            .version("0.1")
            .set_term_width(i)
            .arg(Arg::with_name("cafe")
               .short("c")
               .long("cafe")
               .value_name("FILE")
               .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
               d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
               Le café est souvent une contribution majeure aux exportations des régions productrices.")
               .takes_value(true))
            .get_matches_from_safe(vec!["ctest", "--help"]);
    }
}
<commit_msg>tests: updates tests for new help wrapping rules<commit_after>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, SubCommand, ErrorKind, Arg};

static HELP: &'static str = "clap-test v1.4.8
Kevin K. <kbknapp@gmail.com>
tests clap library

USAGE:
    clap-test [FLAGS] [OPTIONS] [ARGS] [SUBCOMMAND]

FLAGS:
    -f, --flag       tests flags
    -F               tests flags with exclusions
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -O, --Option <option3>           specific vals [values: fast, slow]
        --long-option-2 <option2>    tests long options with exclusions
        --maxvals3 <maxvals>...      Tests 3 max vals
        --minvals2 <minvals>...      Tests 2 min vals
        --multvals <one> <two>       Tests mutliple values, not mult occs
        --multvalsmo <one> <two>     Tests mutliple values, and mult occs
    -o, --option <opt>...            tests options

ARGS:
    <positional>        tests positionals
    <positional2>       tests positionals with exclusions
    <positional3>...    tests specific values [values: vi, emacs]

SUBCOMMANDS:
    help      Prints this message or the help of the given subcommand(s)
    subcmd    tests subcommands";

static AFTER_HELP: &'static str = "some text that comes before the help

clap-test v1.4.8
tests clap library

USAGE:
    clap-test

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

some text that comes after the help";

static SC_HELP: &'static str = "subcmd 0.1
Kevin K. <kbknapp@gmail.com>
tests subcommands

USAGE:
    subcmd [FLAGS] [OPTIONS] [--] [scpositional]

FLAGS:
    -f, --flag    tests flags

OPTIONS:
    -o, --option <scoption>...    tests options

ARGS:
    <scpositional>    tests positionals";

static MULTI_SC_HELP: &'static str = "ctest-subcmd-multi 0.1
Kevin K. <kbknapp@gmail.com>
tests subcommands

USAGE:
    ctest subcmd multi [FLAGS] [OPTIONS]

FLAGS:
    -f, --flag       tests flags
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -o, --option <scoption>...    tests options";

static ISSUE_626_CUTOFF: &'static str = "ctest 0.1

USAGE:
    ctest [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --cafe <FILE>    A coffeehouse, coffee shop, or café is an
                         establishment which primarily serves hot
                         coffee, related coffee beverages (e.g., café
                         latte, cappuccino, espresso), tea, and other
                         hot beverages. Some coffeehouses also serve
                         cold beverages such as iced coffee and iced
                         tea. Many cafés also serve some type of
                         food, such as light snacks, muffins, or
                         pastries.";

static ISSUE_626_PANIC: &'static str = "ctest 0.1

USAGE:
    ctest [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --cafe <FILE>
            La culture du café est très développée
            dans de nombreux pays à climat chaud
            d\'Amérique, d\'Afrique et d\'Asie, dans
            des plantations qui sont cultivées pour
            les marchés d\'exportation. Le café est
            souvent une contribution majeure aux
            exportations des régions productrices.";

#[test]
fn help_short() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "-h"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn help_long() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "--help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn help_no_subcommand() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .get_matches_from_safe(vec!["myprog", "help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
}

#[test]
fn help_subcommand() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .subcommand(SubCommand::with_name("test")
            .about("tests things")
            .arg_from_usage("-v --verbose 'with verbosity'"))
        .get_matches_from_safe(vec!["myprog", "help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_short_help() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_long_help() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn subcommand_help_rev() {
    let m = test::complex_app()
        .get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);

    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn complex_help_output() {
    test::check_help(test::complex_app(), HELP);
}

#[test]
fn after_and_before_help_output() {
    let app = App::new("clap-test")
        .version("v1.4.8")
        .about("tests clap library")
        .before_help("some text that comes before the help")
        .after_help("some text that comes after the help");
    test::check_help(app, AFTER_HELP);
}

#[test]
fn multi_level_sc_help() {
    let app = App::new("ctest")
        .subcommand(SubCommand::with_name("subcmd")
            .subcommand(SubCommand::with_name("multi")
                .about("tests subcommands")
                .author("Kevin K. <kbknapp@gmail.com>")
                .version("0.1")
                .args_from_usage("
                    -f, --flag                    'tests flags'
                    -o, --option [scoption]...    'tests options'
                ")));
    test::check_err_output(app, "ctest help subcmd multi", MULTI_SC_HELP, false);
}

#[test]
fn no_wrap_help() {
    let app = App::new("ctest")
        .set_term_width(0)
        .help(MULTI_SC_HELP);
    test::check_err_output(app, "ctest --help", MULTI_SC_HELP, false);
}

#[test]
fn complex_subcommand_help_output() {
    let mut a = test::complex_app();
    let _ = a.get_matches_from_safe_borrow(vec![""]);
    let sc = a.p.subcommands.iter().filter(|s| s.p.meta.name == "subcmd").next().unwrap();
    // Now we check the output of print_help()
    let mut help = vec![];
    sc.write_help(&mut help).ok().expect("failed to print help");
    assert_eq!(&*String::from_utf8(help).unwrap(), SC_HELP);
}

#[test]
fn issue_626_unicode_cutoff() {
    let app = App::new("ctest")
        .version("0.1")
        .set_term_width(70)
        .arg(Arg::with_name("cafe")
           .short("c")
           .long("cafe")
           .value_name("FILE")
           .help("A coffeehouse, coffee shop, or café is an establishment \
           which primarily serves hot coffee, related coffee beverages \
           (e.g., café latte, cappuccino, espresso), tea, and other hot \
           beverages. Some coffeehouses also serve cold beverages such as \
           iced coffee and iced tea. Many cafés also serve some type of \
           food, such as light snacks, muffins, or pastries.")
           .takes_value(true));
    test::check_err_output(app, "ctest --help", ISSUE_626_CUTOFF, false);
}

#[test]
fn issue_626_panic() {
    let app = App::new("ctest")
        .version("0.1")
        .set_term_width(52)
        .arg(Arg::with_name("cafe")
           .short("c")
           .long("cafe")
           .value_name("FILE")
           .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
           d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
           Le café est souvent une contribution majeure aux exportations des régions productrices.")
           .takes_value(true));
    test::check_err_output(app, "ctest --help", ISSUE_626_PANIC, false);
}

#[test]
fn issue_626_variable_panic() {
    for i in 10..320 {
        let _ = App::new("ctest")
            .version("0.1")
            .set_term_width(i)
            .arg(Arg::with_name("cafe")
               .short("c")
               .long("cafe")
               .value_name("FILE")
               .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
               d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
               Le café est souvent une contribution majeure aux exportations des régions productrices.")
               .takes_value(true))
            .get_matches_from_safe(vec!["ctest", "--help"]);
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate lzma_rs;
#[macro_use]
extern crate log;

fn round_trip(x: &[u8]) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();
    info!("Compressed {} -> {} bytes", x.len(), compressed.len());
    debug!("Compressed content: {:?}", compressed);
    let mut bf = std::io::BufReader::new(compressed.as_slice());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    assert_eq!(decomp, x)
}

fn round_trip_with_options(
    x: &[u8],
    encode_options: &lzma_rs::compress::Options,
    decode_options: &lzma_rs::decompress::Options,
) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress_with_options(
        &mut std::io::BufReader::new(x),
        &mut compressed,
        encode_options,
    )
    .unwrap();
    info!("Compressed {} -> {} bytes", x.len(), compressed.len());
    debug!("Compressed content: {:?}", compressed);
    let mut bf = std::io::BufReader::new(compressed.as_slice());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress_with_options(&mut bf, &mut decomp, decode_options).unwrap();
    assert_eq!(decomp, x)
}

fn round_trip_file(filename: &str) {
    use std::io::Read;

    let mut x = Vec::new();
    std::fs::File::open(filename)
        .unwrap()
        .read_to_end(&mut x)
        .unwrap();
    round_trip(x.as_slice());
}

fn decomp_big_file(compfile: &str, plainfile: &str) {
    use std::io::Read;

    let mut expected = Vec::new();
    std::fs::File::open(plainfile)
        .unwrap()
        .read_to_end(&mut expected)
        .unwrap();
    let mut f = std::io::BufReader::new(std::fs::File::open(compfile).unwrap());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut f, &mut decomp).unwrap();
    assert!(decomp == expected)
}

#[test]
fn decompress_short_header() {
    let _ = env_logger::try_init();
    let mut decomp: Vec<u8> = Vec::new();
    // TODO: compare io::Errors?
    assert_eq!(
        format!(
            "{:?}",
            lzma_rs::lzma_decompress(&mut b"", &mut decomp).unwrap_err()
        ),
        String::from("LZMAError(\"LZMA header too short: failed to fill whole buffer\")")
    )
}

#[test]
fn round_trip_basics() {
    let _ = env_logger::try_init();
    round_trip(b"");
    // Note: we use vec! to avoid storing the slice in the binary
    round_trip(vec![0x00; 1_000_000].as_slice());
    round_trip(vec![0xFF; 1_000_000].as_slice());
}

#[test]
fn round_trip_hello() {
    let _ = env_logger::try_init();
    round_trip(b"Hello world");
}

#[test]
fn round_trip_files() {
    let _ = env_logger::try_init();
    round_trip_file("tests/files/foo.txt");
    round_trip_file("tests/files/range-coder-edge-case");
}

#[test]
fn big_file() {
    let _ = env_logger::try_init();
    decomp_big_file("tests/files/foo.txt.lzma", "tests/files/foo.txt");
    decomp_big_file("tests/files/hugedict.txt.lzma", "tests/files/foo.txt");
    decomp_big_file(
        "tests/files/range-coder-edge-case.lzma",
        "tests/files/range-coder-edge-case",
    );
}

#[test]
fn decompress_empty_world() {
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x83\xff\
                         \xfb\xff\xff\xc0\x00\x00\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"")
}

#[test]
fn decompress_hello_world() {
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x19\
                         \x49\x98\x6f\x10\x19\xc6\xd7\x31\xeb\x36\x50\xb2\x98\x48\xff\xfe\
                         \xa5\xb0\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"Hello world\x0a")
}

#[test]
fn decompress_huge_dict() {
    // Hello world with a dictionary of size 0x7F7F7F7F
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x7f\x7f\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x19\
                         \x49\x98\x6f\x10\x19\xc6\xd7\x31\xeb\x36\x50\xb2\x98\x48\xff\xfe\
                         \xa5\xb0\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"Hello world\x0a")
}

#[test]
fn unpacked_size_write_to_header() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(Some(data.len() as u64)),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadFromHeader,
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_provided_outside() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::SkipWritingToHeader,
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::UseProvided(Some(data.len() as u64)),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_some_to_header_but_use_provided_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(Some(data.len() as u64)),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(Some(
            data.len() as u64,
        )),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_none_to_header_and_use_provided_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(None),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(Some(
            data.len() as u64,
        )),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_none_to_header_and_use_provided_none_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(None),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(None),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}
<commit_msg>Fix invalid Clippy suggestion.<commit_after>extern crate env_logger;
extern crate lzma_rs;
#[macro_use]
extern crate log;

fn round_trip(x: &[u8]) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();
    info!("Compressed {} -> {} bytes", x.len(), compressed.len());
    debug!("Compressed content: {:?}", compressed);
    let mut bf = std::io::BufReader::new(compressed.as_slice());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    assert_eq!(decomp, x)
}

fn round_trip_with_options(
    x: &[u8],
    encode_options: &lzma_rs::compress::Options,
    decode_options: &lzma_rs::decompress::Options,
) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress_with_options(
        &mut std::io::BufReader::new(x),
        &mut compressed,
        encode_options,
    )
    .unwrap();
    info!("Compressed {} -> {} bytes", x.len(), compressed.len());
    debug!("Compressed content: {:?}", compressed);
    let mut bf = std::io::BufReader::new(compressed.as_slice());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress_with_options(&mut bf, &mut decomp, decode_options).unwrap();
    assert_eq!(decomp, x)
}

fn round_trip_file(filename: &str) {
    use std::io::Read;

    let mut x = Vec::new();
    std::fs::File::open(filename)
        .unwrap()
        .read_to_end(&mut x)
        .unwrap();
    round_trip(x.as_slice());
}

fn decomp_big_file(compfile: &str, plainfile: &str) {
    use std::io::Read;

    let mut expected = Vec::new();
    std::fs::File::open(plainfile)
        .unwrap()
        .read_to_end(&mut expected)
        .unwrap();
    let mut f = std::io::BufReader::new(std::fs::File::open(compfile).unwrap());
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut f, &mut decomp).unwrap();
    assert!(decomp == expected)
}

#[test]
fn decompress_short_header() {
    let _ = env_logger::try_init();
    let mut decomp: Vec<u8> = Vec::new();
    // TODO: compare io::Errors?
    assert_eq!(
        format!(
            "{:?}",
            lzma_rs::lzma_decompress(&mut (b"" as &[u8]), &mut decomp).unwrap_err()
        ),
        String::from("LZMAError(\"LZMA header too short: failed to fill whole buffer\")")
    )
}

#[test]
fn round_trip_basics() {
    let _ = env_logger::try_init();
    round_trip(b"");
    // Note: we use vec! to avoid storing the slice in the binary
    round_trip(vec![0x00; 1_000_000].as_slice());
    round_trip(vec![0xFF; 1_000_000].as_slice());
}

#[test]
fn round_trip_hello() {
    let _ = env_logger::try_init();
    round_trip(b"Hello world");
}

#[test]
fn round_trip_files() {
    let _ = env_logger::try_init();
    round_trip_file("tests/files/foo.txt");
    round_trip_file("tests/files/range-coder-edge-case");
}

#[test]
fn big_file() {
    let _ = env_logger::try_init();
    decomp_big_file("tests/files/foo.txt.lzma", "tests/files/foo.txt");
    decomp_big_file("tests/files/hugedict.txt.lzma", "tests/files/foo.txt");
    decomp_big_file(
        "tests/files/range-coder-edge-case.lzma",
        "tests/files/range-coder-edge-case",
    );
}

#[test]
fn decompress_empty_world() {
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x83\xff\
                         \xfb\xff\xff\xc0\x00\x00\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"")
}

#[test]
fn decompress_hello_world() {
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x19\
                         \x49\x98\x6f\x10\x19\xc6\xd7\x31\xeb\x36\x50\xb2\x98\x48\xff\xfe\
                         \xa5\xb0\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"Hello world\x0a")
}

#[test]
fn decompress_huge_dict() {
    // Hello world with a dictionary of size 0x7F7F7F7F
    let _ = env_logger::try_init();
    let mut x: &[u8] = b"\x5d\x7f\x7f\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x19\
                         \x49\x98\x6f\x10\x19\xc6\xd7\x31\xeb\x36\x50\xb2\x98\x48\xff\xfe\
                         \xa5\xb0\x00";
    let mut decomp: Vec<u8> = Vec::new();
    lzma_rs::lzma_decompress(&mut x, &mut decomp).unwrap();
    assert_eq!(decomp, b"Hello world\x0a")
}

#[test]
fn unpacked_size_write_to_header() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(Some(data.len() as u64)),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadFromHeader,
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_provided_outside() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::SkipWritingToHeader,
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::UseProvided(Some(data.len() as u64)),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_some_to_header_but_use_provided_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(Some(data.len() as u64)),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(Some(
            data.len() as u64,
        )),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_none_to_header_and_use_provided_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(None),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(Some(
            data.len() as u64,
        )),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}

#[test]
fn unpacked_size_write_none_to_header_and_use_provided_none_on_read() {
    let data = b"Some data";
    let encode_options = lzma_rs::compress::Options {
        unpacked_size: lzma_rs::compress::UnpackedSize::WriteToHeader(None),
    };
    let decode_options = lzma_rs::decompress::Options {
        unpacked_size: lzma_rs::decompress::UnpackedSize::ReadHeaderButUseProvided(None),
    };
    round_trip_with_options(&data[..], &encode_options, &decode_options);
}
<|endoftext|>


<commit_before>extern crate phf_codegen;

use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() {
    generate_phf_of_svg_attributes();
}

/// Creates a perfect hash function (PHF) to map SVG attribute names to enum values.
fn generate_phf_of_svg_attributes() {
    // (attribute name, Rust enum value, C enum value suffix
    let attribute_defs = [
        ( "alternate",          "Alternate",          "ALTERNATE" ),
        ( "amplitude",          "Amplitude",          "AMPLITUDE" ),
        ( "azimuth",            "Azimuth",            "AZIMUTH" ),
        ( "baseFrequency",      "BaseFrequency",      "BASE_FREQUENCY" ),
        ( "baseline-shift",     "BaselineShift",      "BASELINE_SHIFT" ),
        ( "bias",               "Bias",               "BIAS" ),
        ( "class",              "Class",              "CLASS" ),
        ( "clip-path",          "ClipPath",           "CLIP_PATH" ),
        ( "clip-rule",          "ClipRule",           "CLIP_RULE" ),
        ( "color",              "Color",              "COLOR" ),
        ( "comp-op",            "CompOp",             "COMP_OP" ),
        ( "diffuseConstant",    "DiffuseConstant",    "DIFFUSE_CONSTANT" ),
        ( "direction",          "Direction",          "DIRECTION" ),
        ( "display",            "Display",            "DISPLAY" ),
        ( "divisor",            "Divisor",            "DIVISOR" ),
        ( "dx",                 "Dx",                 "DX" ),
        ( "dy",                 "Dy",                 "DY" ),
        ( "edgeMode",           "EdgeMode",           "EDGE_MODE" ),
        ( "elevation",          "Elevation",          "ELEVATION" ),
        ( "enable-background",  "EnableBackground",   "ENABLE_BACKGROUND" ),
        ( "encoding",           "Encoding",           "ENCODING" ),
        ( "exponent",           "Exponent",           "EXPONENT" ),
        ( "fill",               "Fill",               "FILL" ),
        ( "fill-opacity",       "FillOpacity",        "FILL_OPACITY" ),
        ( "fill-rule",          "FillRule",           "FILL_RULE" ),
        ( "filter",             "Filter",             "FILTER" ),
        ( "filterUnits",        "FilterUnits",        "FILTERUNITS" ),
        ( "flood-color",        "FloodColor",         "FLOOD_COLOR" ),
        ( "flood-opacity",      "FloodOpacity",       "FLOOD_OPACITY" ),
        ( "font-family",        "FontFamily",         "FONT_FAMILY" ),
        ( "font-size",          "FontSize",           "FONT_SIZE" ),
        ( "font-stretch",       "FontStretch",        "FONT_STRETCH" ),
        ( "font-style",         "FontStyle",          "FONT_STYLE" ),
        ( "font-variant",       "FontVariant",        "FONT_VARIANT" ),
        ( "font-weight",        "FontWeight",         "FONT_WEIGHT" ),
        ( "height",             "Height",             "HEIGHT" ),
        ( "href",               "Href",               "HREF" ),
        ( "id",                 "Id",                 "ID" ),
        ( "in",                 "In",                 "IN" ),
        ( "in2",                "In2",                "IN2" ),
        ( "intercept",          "Intercept",          "INTERCEPT" ),
        ( "k1",                 "K1",                 "K1" ),
        ( "k2",                 "K2",                 "K2" ),
        ( "k3",                 "K3",                 "K3" ),
        ( "k4",                 "K4",                 "K4" ),
        ( "kernelMatrix",       "KernelMatrix",       "KERNEL_MATRIX" ),
        ( "kernelUnitLength",   "KernelUnitLength",   "KERNEL_UNIT_LENGTH" ),
        ( "letter-spacing",     "LetterSpacing",      "LETTER_SPACING" ),
        ( "lighting-color",     "LightingColor",      "LIGHTING_COLOR" ),
        ( "limitingConeAngle",  "LimitingConeAngle",  "LIMITING_CONE_ANGLE" ),
        ( "marker",             "Marker",             "MARKER" ),
        ( "marker-end",         "MarkerEnd",          "MARKER_END" ),
        ( "marker-mid",         "MarkerMid",          "MARKER_MID" ),
        ( "marker-start",       "MarkerStart",        "MARKER_START" ),
        ( "mask",               "Mask",               "MASK" ),
        ( "mode",               "Mode",               "MODE" ),
        ( "numOctaves",         "NumOctaves",         "NUM_OCTAVES" ),
        ( "offset",             "Offset",             "OFFSET" ),
        ( "opacity",            "Opacity",            "OPACITY" ),
        ( "operator",           "Operator",           "OPERATOR" ),
        ( "order",              "Order",              "ORDER" ),
        ( "overflow",           "Overflow",           "OVERFLOW" ),
        ( "parse",              "Parse",              "PARSE" ),
        ( "pointsAtX",          "PointsAtX",          "POINTS_AT_X" ),
        ( "pointsAtY",          "PointsAtY",          "POINTS_AT_Y" ),
        ( "pointsAtZ",          "PointsAtZ",          "POINTS_AT_Z" ),
        ( "preserveAlpha",      "PreserveAlpha",      "PRESERVE_ALPHA" ),
        ( "primitiveUnits",     "PrimitiveUnits",     "PRIMITIVE_UNITS" ),
        ( "radius",             "Radius",             "RADIUS" ),
        ( "requiredExtensions", "RequiredExtensions", "REQUIRED_EXTENSIONS" ),
        ( "requiredFeatures",   "RequiredFeatures",   "REQUIRED_FEATURES" ),
        ( "result",             "Result",             "RESULT" ),
        ( "scale",              "Scale",              "SCALE" ),
        ( "seed",               "Seed",               "SEED" ),
        ( "shape-rendering",    "ShapeRendering",     "SHAPE_RENDERING" ),
        ( "slope",              "Slope",              "SLOPE" ),
        ( "specularConstant",   "SpecularConstant",   "SPECULAR_CONSTANT" ),
        ( "specularExponent",   "SpecularExponent",   "SPECULAR_EXPONENT" ),
        ( "stdDeviation",       "StdDeviation",       "STD_DEVIATION" ),
        ( "stitchTiles",        "StitchTiles",        "STITCH_TILES" ),
        ( "stop-color",         "StopColor",          "STOP_COLOR" ),
        ( "stop-opacity",       "StopOpacity",        "STOP_OPACITY" ),
        ( "stroke",             "Stroke",             "STROKE" ),
        ( "stroke-dasharray",   "StrokeDasharray",    "STROKE_DASHARRAY" ),
        ( "stroke-dashoffset",  "StrokeDashoffset",   "STROKE_DASHOFFSET" ),
        ( "stroke-linecap",     "StrokeLinecap",      "STROKE_LINECAP" ),
        ( "stroke-linejoin",    "StrokeLinejoin",     "STROKE_LINEJOIN" ),
        ( "stroke-miterlimit",  "StrokeMiterlimit",   "STROKE_MITERLIMIT" ),
        ( "stroke-opacity",     "StrokeOpacity",      "STROKE_OPACITY" ),
        ( "stroke-width",       "StrokeWidth",        "STROKE_WIDTH" ),
        ( "style",              "Style",              "STYLE" ),
        ( "surfaceScale",       "SurfaceScale",       "SURFACE_SCALE" ),
        ( "systemLanguage",     "SystemLanguage",     "SYSTEM_LANGUAGE" ),
        ( "tableValues",        "TableValues",        "TABLE_VALUES" ),
        ( "targetX",            "TargetX",            "TARGET_X" ),
        ( "targetY",            "TargetY",            "TARGET_Y" ),
        ( "text-anchor",        "TextAnchor",         "TEXT_ANCHOR" ),
        ( "text-decoration",    "TextDecoration",     "TEXT_DECORATION" ),
        ( "text-rendering",     "TextRendering",      "TEXT_RENDERING" ),
        ( "transform",          "Transform",          "TRANSFORM" ),
        ( "type",               "Type",               "TYPE" ),
        ( "unicode-bidi",       "UnicodeBidi",        "UNICODE_BIDI" ),
        ( "values",             "Values",             "VALUES" ),
        ( "visibility",         "Visibility",         "VISIBILITY" ),
        ( "width",              "Width",              "WIDTH" ),
        ( "writing-mode",       "WritingMode",        "WRITING_MODE" ),
        ( "x",                  "X",                  "X" ),
        ( "xChannelSelector",   "XChannelSelector",   "X_CHANNEL_SELECTOR" ),
        ( "xlink:href",         "XlinkHref",          "XLINK_HREF" ),
        ( "xml:lang",           "XmlLang",            "XML_LANG" ),
        ( "xml:space",          "XmlSpace",           "XML_SPACE" ),
        ( "y",                  "Y",                  "Y" ),
        ( "yChannelSelector",   "YChannelSelector",   "Y_CHANNEL_SELECTOR" ),
        ( "z",                  "Z",                  "Z" ),
    ];

    let path = Path::new(&env::var("OUT_DIR").unwrap()).join("attributes-codegen.rs");
    let mut file = BufWriter::new(File::create(&path).unwrap());

    writeln!(&mut file, "#[repr(C)]").unwrap();
    writeln!(&mut file, "#[derive(Debug, Clone, Copy, PartialEq)]").unwrap();
    writeln!(&mut file, "pub enum Attribute {{").unwrap();

    for &(_, rust, _) in attribute_defs.iter() {
        writeln!(&mut file, "    {},", rust).unwrap();
    }

    writeln!(&mut file, "}}").unwrap();

    writeln!(&mut file, "static ATTRIBUTES: phf::Map<&'static str, Attribute> = ").unwrap();

    let mut map = phf_codegen::Map::new();
    map.phf_path("phf");
    for &(name, rust, _) in attribute_defs.iter() {
        let rust = ["Attribute::", rust].concat();
        map.entry(name, &rust);
    }

    map.build(&mut file).unwrap();
    writeln!(&mut file, ";").unwrap();
}
<commit_msg>build.rs: We don't need the C names after all<commit_after>extern crate phf_codegen;

use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() {
    generate_phf_of_svg_attributes();
}

/// Creates a perfect hash function (PHF) to map SVG attribute names to enum values.
fn generate_phf_of_svg_attributes() {
    // (attribute name, Rust enum value)
    //
    // Keep this in sync with rsvg-attributes.h
    let attribute_defs = [
        ( "alternate",          "Alternate" ),
        ( "amplitude",          "Amplitude" ),
        ( "azimuth",            "Azimuth" ),
        ( "baseFrequency",      "BaseFrequency" ),
        ( "baseline-shift",     "BaselineShift" ),
        ( "bias",               "Bias" ),
        ( "class",              "Class" ),
        ( "clip-path",          "ClipPath" ),
        ( "clip-rule",          "ClipRule" ),
        ( "color",              "Color" ),
        ( "comp-op",            "CompOp" ),
        ( "diffuseConstant",    "DiffuseConstant" ),
        ( "direction",          "Direction" ),
        ( "display",            "Display" ),
        ( "divisor",            "Divisor" ),
        ( "dx",                 "Dx" ),
        ( "dy",                 "Dy" ),
        ( "edgeMode",           "EdgeMode" ),
        ( "elevation",          "Elevation" ),
        ( "enable-background",  "EnableBackground" ),
        ( "encoding",           "Encoding" ),
        ( "exponent",           "Exponent" ),
        ( "fill",               "Fill" ),
        ( "fill-opacity",       "FillOpacity" ),
        ( "fill-rule",          "FillRule" ),
        ( "filter",             "Filter" ),
        ( "filterUnits",        "FilterUnits" ),
        ( "flood-color",        "FloodColor" ),
        ( "flood-opacity",      "FloodOpacity" ),
        ( "font-family",        "FontFamily" ),
        ( "font-size",          "FontSize" ),
        ( "font-stretch",       "FontStretch" ),
        ( "font-style",         "FontStyle" ),
        ( "font-variant",       "FontVariant" ),
        ( "font-weight",        "FontWeight" ),
        ( "height",             "Height" ),
        ( "href",               "Href" ),
        ( "id",                 "Id" ),
        ( "in",                 "In" ),
        ( "in2",                "In2" ),
        ( "intercept",          "Intercept" ),
        ( "k1",                 "K1" ),
        ( "k2",                 "K2" ),
        ( "k3",                 "K3" ),
        ( "k4",                 "K4" ),
        ( "kernelMatrix",       "KernelMatrix" ),
        ( "kernelUnitLength",   "KernelUnitLength" ),
        ( "letter-spacing",     "LetterSpacing" ),
        ( "lighting-color",     "LightingColor" ),
        ( "limitingConeAngle",  "LimitingConeAngle" ),
        ( "marker",             "Marker" ),
        ( "marker-end",         "MarkerEnd" ),
        ( "marker-mid",         "MarkerMid" ),
        ( "marker-start",       "MarkerStart" ),
        ( "mask",               "Mask" ),
        ( "mode",               "Mode" ),
        ( "numOctaves",         "NumOctaves" ),
        ( "offset",             "Offset" ),
        ( "opacity",            "Opacity" ),
        ( "operator",           "Operator" ),
        ( "order",              "Order" ),
        ( "overflow",           "Overflow" ),
        ( "parse",              "Parse" ),
        ( "pointsAtX",          "PointsAtX" ),
        ( "pointsAtY",          "PointsAtY" ),
        ( "pointsAtZ",          "PointsAtZ" ),
        ( "preserveAlpha",      "PreserveAlpha" ),
        ( "primitiveUnits",     "PrimitiveUnits" ),
        ( "radius",             "Radius" ),
        ( "requiredExtensions", "RequiredExtensions" ),
        ( "requiredFeatures",   "RequiredFeatures" ),
        ( "result",             "Result" ),
        ( "scale",              "Scale" ),
        ( "seed",               "Seed" ),
        ( "shape-rendering",    "ShapeRendering" ),
        ( "slope",              "Slope" ),
        ( "specularConstant",   "SpecularConstant" ),
        ( "specularExponent",   "SpecularExponent" ),
        ( "stdDeviation",       "StdDeviation" ),
        ( "stitchTiles",        "StitchTiles" ),
        ( "stop-color",         "StopColor" ),
        ( "stop-opacity",       "StopOpacity" ),
        ( "stroke",             "Stroke" ),
        ( "stroke-dasharray",   "StrokeDasharray" ),
        ( "stroke-dashoffset",  "StrokeDashoffset" ),
        ( "stroke-linecap",     "StrokeLinecap" ),
        ( "stroke-linejoin",    "StrokeLinejoin" ),
        ( "stroke-miterlimit",  "StrokeMiterlimit" ),
        ( "stroke-opacity",     "StrokeOpacity" ),
        ( "stroke-width",       "StrokeWidth" ),
        ( "style",              "Style" ),
        ( "surfaceScale",       "SurfaceScale" ),
        ( "systemLanguage",     "SystemLanguage" ),
        ( "tableValues",        "TableValues" ),
        ( "targetX",            "TargetX" ),
        ( "targetY",            "TargetY" ),
        ( "text-anchor",        "TextAnchor" ),
        ( "text-decoration",    "TextDecoration" ),
        ( "text-rendering",     "TextRendering" ),
        ( "transform",          "Transform" ),
        ( "type",               "Type" ),
        ( "unicode-bidi",       "UnicodeBidi" ),
        ( "values",             "Values" ),
        ( "visibility",         "Visibility" ),
        ( "width",              "Width" ),
        ( "writing-mode",       "WritingMode" ),
        ( "x",                  "X" ),
        ( "xChannelSelector",   "XChannelSelector" ),
        ( "xlink:href",         "XlinkHref" ),
        ( "xml:lang",           "XmlLang" ),
        ( "xml:space",          "XmlSpace" ),
        ( "y",                  "Y" ),
        ( "yChannelSelector",   "YChannelSelector" ),
        ( "z",                  "Z" ),
    ];

    let path = Path::new(&env::var("OUT_DIR").unwrap()).join("attributes-codegen.rs");
    let mut file = BufWriter::new(File::create(&path).unwrap());

    writeln!(&mut file, "#[repr(C)]").unwrap();
    writeln!(&mut file, "#[derive(Debug, Clone, Copy, PartialEq)]").unwrap();
    writeln!(&mut file, "pub enum Attribute {{").unwrap();

    for &(_, valname) in attribute_defs.iter() {
        writeln!(&mut file, "    {},", valname).unwrap();
    }

    writeln!(&mut file, "}}").unwrap();

    writeln!(&mut file, "static ATTRIBUTES: phf::Map<&'static str, Attribute> = ").unwrap();

    let mut map = phf_codegen::Map::new();
    map.phf_path("phf");
    for &(name, valname) in attribute_defs.iter() {
        let valname = ["Attribute::", valname].concat();
        map.entry(name, &valname);
    }

    map.build(&mut file).unwrap();
    writeln!(&mut file, ";").unwrap();
}
<|endoftext|>


<commit_before>extern crate clap;

use clap::{App, Arg};

#[test]
fn posix_compatible_flags_long() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color 'some other flag'"))
                .get_matches_from(vec!["", "--flag", "--color"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color 'some other flag'"))
                .get_matches_from(vec!["", "--color", "--flag"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
}

#[test]
fn posix_compatible_flags_short() {
    let m = App::new("posix")
                .arg(Arg::from_usage("-f, --flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c, --color 'some other flag'"))
                .get_matches_from(vec!["", "-f", "-c"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("-f, --flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c, --color 'some other flag'"))
                .get_matches_from(vec!["", "-c", "-f"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
}

#[test]
fn posix_compatible_opts_long() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--flag", "some" ,"--color", "other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--color", "some" ,"--flag", "other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}

#[test]
fn posix_compatible_opts_long_equals() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--flag=some" ,"--color=other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--color=some" ,"--flag=other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}

#[test]
fn posix_compatible_opts_short() {
    let m = App::new("posix")
                .arg(Arg::from_usage("-f [flag]  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c [color] 'some other flag'"))
                .get_matches_from(vec!["", "-f", "some", "-c", "other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("-f [flag]  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c [color] 'some other flag'"))
                .get_matches_from(vec!["", "-c", "some", "-f", "other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}<commit_msg>tests: conflict override tests<commit_after>extern crate clap;

use clap::{App, Arg, ClapErrorType  };

#[test]
fn posix_compatible_flags_long() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color 'some other flag'"))
                .get_matches_from(vec!["", "--flag", "--color"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color 'some other flag'"))
                .get_matches_from(vec!["", "--color", "--flag"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
}

#[test]
fn posix_compatible_flags_short() {
    let m = App::new("posix")
                .arg(Arg::from_usage("-f, --flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c, --color 'some other flag'"))
                .get_matches_from(vec!["", "-f", "-c"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("-f, --flag  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c, --color 'some other flag'"))
                .get_matches_from(vec!["", "-c", "-f"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
}

#[test]
fn posix_compatible_opts_long() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--flag", "some" ,"--color", "other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--color", "some" ,"--flag", "other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}

#[test]
fn posix_compatible_opts_long_equals() {
    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--flag=some" ,"--color=other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("--flag [flag] 'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("--color [color] 'some other flag'"))
                .get_matches_from(vec!["", "--color=some" ,"--flag=other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}

#[test]
fn posix_compatible_opts_short() {
    let m = App::new("posix")
                .arg(Arg::from_usage("-f [flag]  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c [color] 'some other flag'"))
                .get_matches_from(vec!["", "-f", "some", "-c", "other"]);
    assert!(m.is_present("color"));
    assert_eq!(m.value_of("color").unwrap(), "other");
    assert!(!m.is_present("flag"));

    let m = App::new("posix")
                .arg(Arg::from_usage("-f [flag]  'some flag'").mutually_overrides_with("color"))
                .arg(Arg::from_usage("-c [color] 'some other flag'"))
                .get_matches_from(vec!["", "-c", "some", "-f", "other"]);
    assert!(!m.is_present("color"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("flag").unwrap(), "other");
}

#[test]
fn conflict_overriden() {
    let m = App::new("conflict_overriden")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("debug"))
        .arg(Arg::from_usage("-d, --debug 'other flag'"))
        .arg(Arg::from_usage("-c, --color 'third flag'")
            .mutually_overrides_with("flag"))
        .get_matches_from(vec!["", "-f", "-c", "-d"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));
    assert!(m.is_present("debug"));
}

#[test]
fn conflict_overriden_2() {
    let result = App::new("conflict_overriden")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("debug"))
        .arg(Arg::from_usage("-d, --debug 'other flag'"))
        .arg(Arg::from_usage("-c, --color 'third flag'")
            .mutually_overrides_with("flag"))
        .get_matches_from_safe(vec!["", "-f", "-d", "-c"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.error_type, ClapErrorType::ArgumentConflict);
}

#[test]
fn conflict_overriden_3() {
    let result = App::new("conflict_overriden")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("debug"))
        .arg(Arg::from_usage("-d, --debug 'other flag'"))
        .arg(Arg::from_usage("-c, --color 'third flag'")
            .mutually_overrides_with("flag"))
        .get_matches_from_safe(vec!["", "-d", "-c", "-f"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.error_type, ClapErrorType::ArgumentConflict);
}

#[test]
fn conflict_overriden_4() {
    let m = App::new("conflict_overriden")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("debug"))
        .arg(Arg::from_usage("-d, --debug 'other flag'"))
        .arg(Arg::from_usage("-c, --color 'third flag'")
            .mutually_overrides_with("flag"))
        .get_matches_from(vec!["", "-d", "-f", "-c"]);
    assert!(m.is_present("color"));
    assert!(!m.is_present("flag"));
    assert!(m.is_present("debug"));
}<|endoftext|>


<commit_before>use std::net::TcpStream;
use std::collections::HashMap;
use std::io;
use std::io::{Read,Write};
use std::ops::Deref;
use libc;

use unix_socket::UnixStream;
use rustc_serialize::hex::ToHex;
use dbus_serialize::types::{Value,BasicValue};
use dbus_serialize::decoder::DBusDecoder;

use message;
use message::{Message,HeaderFieldName,MessageBuf};
use demarshal::{demarshal,DemarshalError};
use marshal::Marshal;

trait StreamSocket : Read + Write { }

impl StreamSocket for TcpStream { }
impl StreamSocket for UnixStream { }

enum Socket {
    Tcp(TcpStream),
    Uds(UnixStream)
}

pub struct Connection {
    sock: Socket,
    next_serial: u32
}

#[derive(Debug)]
pub enum Error {
    Disconnected,
    IOError(io::Error),
    DemarshalError(DemarshalError),
    BadData,
    AuthFailed,
}

impl From<io::Error> for Error {
    fn from(x: io::Error) -> Self {
        Error::IOError(x)
    }
}

impl From<DemarshalError> for Error {
    fn from(x: DemarshalError) -> Self {
        Error::DemarshalError(x)
    }
}

fn read_exactly(sock: &mut StreamSocket, buf: &mut Vec<u8>, len: usize) -> Result<(),Error> {
    buf.truncate(0);
    buf.reserve(len);
    if try!(sock.take(len as u64).read_to_end(buf)) != len {
        return Err(Error::Disconnected);
    }
    Ok(())
}

fn read_line(sock: &mut StreamSocket) -> Result<String,Error> {
    let mut line = "".to_string();
    let mut last = '\0';

    loop {
        let mut buf = vec![0];
        match sock.read(&mut buf) {
            Ok(x) if x > 0 => (),
            _ => return Err(Error::Disconnected)
        };
        let chr = buf[0] as char;
        line.push(chr);
        if chr == '\n' && last == '\r' {
            break;
        }
        last = chr;
    }
    Ok(line)
}

impl Connection {
    fn get_sock(&mut self) -> &mut StreamSocket {
        match self.sock {
            Socket::Tcp(ref mut x) => x,
            Socket::Uds(ref mut x) => x
        }
    }

    fn auth_anonymous(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        // Authenticate to the daemon
        let buf = vec![0];
        try!(sock.write_all(&buf));

        try!(sock.write_all(b"AUTH ANONYMOUS 6c69626462757320312e382e3132\r\n"));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn auth_external(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        // Authenticate to the daemon
        let buf = vec![0];
        try!(sock.write_all(&buf));

        let uid = unsafe {
            libc::funcs::posix88::unistd::getuid()
        };
        let uid_str = uid.to_string();
        let uid_hex = uid_str.into_bytes().to_hex();
        let cmd = "AUTH EXTERNAL ".to_string() + &uid_hex + "\r\n";
        try!(sock.write_all(&cmd.into_bytes()));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn say_hello(&mut self) -> Result<(),Error> {
        let mut msg = message::create_method_call("org.freedesktop.DBus",
                                                  "/org/freedesktop/DBus",
                                                  "org.freedesktop.DBus",
                                                  "Hello");
        try!(self.send(&mut msg));

        // XXX: validate Hello reply
        let msg = self.read_msg().unwrap();
        println!("{:?}", msg.body);
        Ok(())
    }

    pub fn connect_uds(addr: &str) -> Result<Connection,Error> {
        let sock = try!(UnixStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Uds(sock),
            next_serial: 1
        };

        try!(conn.auth_external());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn connect_tcp(addr: &str) -> Result<Connection,Error> {
        let sock = try!(TcpStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Tcp(sock),
            next_serial: 1
        };

        try!(conn.auth_anonymous());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn send(&mut self, mbuf: &mut MessageBuf) -> Result<(),Error> {
        let mut msg = &mut mbuf.0;
        // A minimum header with no body is 16 bytes
        let mut len = msg.len() as u32;
        if len < 16 {
            return Err(Error::BadData);
        }

        // Get the current length from the message, which only include the length of the header.
        // That field should actually be the length of only the body, so update that now
        let old_len = message::get_length(msg);
        len -= old_len;
        let mut buf = Vec::new();
        len.dbus_encode(&mut buf);
        // Update the message with a correct serial number, as well
        self.next_serial.dbus_encode(&mut buf);
        self.next_serial += 1;
        message::set_length(msg, &buf);

        let sock = self.get_sock();
        try!(sock.write_all(msg));
        Ok(())
    }

    pub fn read_msg(&mut self) -> Result<Message,Error> {
        let mut buf = Vec::new();
        let sock = self.get_sock();

        // Read and demarshal the fixed portion of the header
        try!(read_exactly(sock, &mut buf, 12));
        let mut offset = 0;
        let mut sig = "(yyyyuu)".to_string();
        let header = match try!(demarshal(&mut buf, &mut offset, &mut sig)) {
            Value::Struct(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        let mut v = header.objects;
        let mut msg : Message = Default::default();
        let endian : u8 = DBusDecoder::decode(v.remove(0)).unwrap();
        if endian == 'B' as u8 {
            msg.big_endian = true;
        }
        msg.message_type = message::MessageType(DBusDecoder::decode(v.remove(0)).unwrap());
        msg.flags = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        msg.version = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        let body_len = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();
        msg.serial = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();

        // Read array length
        try!(read_exactly(sock, &mut buf, 4));
        // demarshal consumes the buf, so save a copy for when we demarshal the entire array
        let mut buf_copy = buf.clone();
        offset = 12;
        sig = "u".to_string();
        let data = demarshal(&mut buf, &mut offset, &mut sig).ok().unwrap();
        let arr_len = DBusDecoder::decode::<u32>(data).unwrap() as usize;

        // Make buf_copy big enough for the entire array, and fill it
        buf_copy.reserve(arr_len);
        if try!(sock.take(arr_len as u64).read_to_end(&mut buf_copy)) != arr_len {
            return Err(Error::Disconnected);
        };

        offset = 12;
        sig = "a(yv)".to_string();
        let header_fields = match try!(demarshal(&mut buf_copy, &mut offset, &mut sig)) {
            Value::Array(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        msg.headers = HashMap::new();
        for i in header_fields.objects {
            let mut st = match i {
                Value::Struct(x) => x,
                x => panic!("Demarshal didn't return what we asked for: {:?}", x)
            };
            let val = st.objects.remove(1);
            let code = DBusDecoder::decode::<u8>(st.objects.remove(0)).unwrap();
            msg.headers.insert(code, val);
        }

        // Read the padding, if any
        let trailing_pad = 8 - (offset % 8);
        if trailing_pad % 8 != 0 {
            try!(read_exactly(sock, &mut buf, trailing_pad));
        }

        // Finally, read the entire body
        if body_len > 0 {
            let v = match msg.headers.get(&(HeaderFieldName::Signature as u8)) {
                Some(&Value::Variant(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let sigval = match v.object.deref() {
                &Value::BasicValue(BasicValue::Signature(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let mut body = Vec::new();
            try!(read_exactly(sock, &mut body, body_len as usize));

            let mut sig = "(".to_string() + &sigval.0 + ")";
            offset = 0;
            let objs = match try!(demarshal(&mut body, &mut offset, &mut sig)) {
                Value::Struct(x) => x.objects,
                x => panic!("Didn't get a struct: {:?}", x)
            };
            for x in objs {
                msg.body.push(x);
            }
        }

        Ok(msg)
    }
}

#[test]
fn test_connect () {
    let mut conn = Connection::connect_uds("/var/run/dbus/system_bus_socket").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    conn.send(&mut msg).ok();
    let msg = conn.read_msg().unwrap();
    println!("{:?}", msg.body);
}

#[cfg(tcp)]
#[test]
fn test_tcp () {
    let mut conn = Connection::connect_tcp("localhost:12345").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    conn.send(&mut msg).ok();
    let msg = conn.read_msg().unwrap();
    println!("{:?}", msg.body);
    //loop {
    //    conn.read_msg().unwrap();
    //}
}
<commit_msg>connection.rs: implement call_sync for blocking method calls<commit_after>use std::net::TcpStream;
use std::collections::HashMap;
use std::io;
use std::io::{Read,Write};
use std::ops::Deref;
use libc;

use unix_socket::UnixStream;
use rustc_serialize::hex::ToHex;
use dbus_serialize::types::{Value,BasicValue};
use dbus_serialize::decoder::DBusDecoder;

use message;
use message::{Message,HeaderFieldName,MessageBuf};
use demarshal::{demarshal,DemarshalError};
use marshal::Marshal;

trait StreamSocket : Read + Write { }

impl StreamSocket for TcpStream { }
impl StreamSocket for UnixStream { }

enum Socket {
    Tcp(TcpStream),
    Uds(UnixStream)
}

pub struct Connection {
    sock: Socket,
    next_serial: u32,
    queue: Vec<Message>,
}

#[derive(Debug)]
pub enum Error {
    Disconnected,
    IOError(io::Error),
    DemarshalError(DemarshalError),
    BadData,
    AuthFailed,
}

impl From<io::Error> for Error {
    fn from(x: io::Error) -> Self {
        Error::IOError(x)
    }
}

impl From<DemarshalError> for Error {
    fn from(x: DemarshalError) -> Self {
        Error::DemarshalError(x)
    }
}

fn read_exactly(sock: &mut StreamSocket, buf: &mut Vec<u8>, len: usize) -> Result<(),Error> {
    buf.truncate(0);
    buf.reserve(len);
    if try!(sock.take(len as u64).read_to_end(buf)) != len {
        return Err(Error::Disconnected);
    }
    Ok(())
}

fn read_line(sock: &mut StreamSocket) -> Result<String,Error> {
    let mut line = "".to_string();
    let mut last = '\0';

    loop {
        let mut buf = vec![0];
        match sock.read(&mut buf) {
            Ok(x) if x > 0 => (),
            _ => return Err(Error::Disconnected)
        };
        let chr = buf[0] as char;
        line.push(chr);
        if chr == '\n' && last == '\r' {
            break;
        }
        last = chr;
    }
    Ok(line)
}

impl Connection {
    fn get_sock(&mut self) -> &mut StreamSocket {
        match self.sock {
            Socket::Tcp(ref mut x) => x,
            Socket::Uds(ref mut x) => x
        }
    }

    fn auth_anonymous(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        // Authenticate to the daemon
        let buf = vec![0];
        try!(sock.write_all(&buf));

        try!(sock.write_all(b"AUTH ANONYMOUS 6c69626462757320312e382e3132\r\n"));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn auth_external(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        // Authenticate to the daemon
        let buf = vec![0];
        try!(sock.write_all(&buf));

        let uid = unsafe {
            libc::funcs::posix88::unistd::getuid()
        };
        let uid_str = uid.to_string();
        let uid_hex = uid_str.into_bytes().to_hex();
        let cmd = "AUTH EXTERNAL ".to_string() + &uid_hex + "\r\n";
        try!(sock.write_all(&cmd.into_bytes()));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn say_hello(&mut self) -> Result<(),Error> {
        let mut msg = message::create_method_call("org.freedesktop.DBus",
                                                  "/org/freedesktop/DBus",
                                                  "org.freedesktop.DBus",
                                                  "Hello");
        try!(self.call_sync(&mut msg));
        // XXX: validate Hello reply
        Ok(())
    }

    pub fn connect_uds(addr: &str) -> Result<Connection,Error> {
        let sock = try!(UnixStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Uds(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.auth_external());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn connect_tcp(addr: &str) -> Result<Connection,Error> {
        let sock = try!(TcpStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Tcp(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.auth_anonymous());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn send(&mut self, mbuf: &mut MessageBuf) -> Result<u32, Error> {
        let mut msg = &mut mbuf.0;
        // A minimum header with no body is 16 bytes
        let mut len = msg.len() as u32;
        if len < 16 {
            return Err(Error::BadData);
        }

        // Get the current length from the message, which only include the length of the header.
        // That field should actually be the length of only the body, so update that now
        let old_len = message::get_length(msg);
        len -= old_len;
        let mut buf = Vec::new();
        len.dbus_encode(&mut buf);
        // Update the message with a correct serial number, as well
        let this_serial = self.next_serial;
        self.next_serial += 1;
        this_serial.dbus_encode(&mut buf);
        message::set_length(msg, &buf);

        let sock = self.get_sock();
        try!(sock.write_all(msg));
        Ok(this_serial)
    }

    pub fn call_sync(&mut self, mbuf: &mut MessageBuf) -> Result<Vec<Value>,Error> {
        // XXX: assert that this is a method call with reply
        let serial = try!(self.send(mbuf));
        // We need a local queue so that read_msg doesn't just give us
        // the same one over and over
        let mut queue = Vec::new();
        loop {
            let msg = try!(self.read_msg());
            match msg.headers.get(&(HeaderFieldName::ReplySerial as u8)) {
                Some(&Value::Variant(ref x)) => {
                    let reply_serial : u32 = DBusDecoder::decode(x.object.deref().clone()).unwrap();
                    if reply_serial == serial {
                        // Move our queued messages into the Connection's queue
                        for _ in 0..queue.len() {
                            self.queue.push(queue.remove(0));
                        }
                        return Ok(msg.body);
                    }
                }
                _ => ()
            };
            queue.push(msg);
        }
    }

    pub fn read_msg(&mut self) -> Result<Message,Error> {
        match self.queue.get(0) {
            Some(_) => return Ok(self.queue.remove(0)),
            _ => ()
        };
        let mut buf = Vec::new();
        let sock = self.get_sock();

        // Read and demarshal the fixed portion of the header
        try!(read_exactly(sock, &mut buf, 12));
        let mut offset = 0;
        let mut sig = "(yyyyuu)".to_string();
        let header = match try!(demarshal(&mut buf, &mut offset, &mut sig)) {
            Value::Struct(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        let mut v = header.objects;
        let mut msg : Message = Default::default();
        let endian : u8 = DBusDecoder::decode(v.remove(0)).unwrap();
        if endian == 'B' as u8 {
            msg.big_endian = true;
        }
        msg.message_type = message::MessageType(DBusDecoder::decode(v.remove(0)).unwrap());
        msg.flags = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        msg.version = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        let body_len = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();
        msg.serial = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();

        // Read array length
        try!(read_exactly(sock, &mut buf, 4));
        // demarshal consumes the buf, so save a copy for when we demarshal the entire array
        let mut buf_copy = buf.clone();
        offset = 12;
        sig = "u".to_string();
        let data = demarshal(&mut buf, &mut offset, &mut sig).ok().unwrap();
        let arr_len = DBusDecoder::decode::<u32>(data).unwrap() as usize;

        // Make buf_copy big enough for the entire array, and fill it
        buf_copy.reserve(arr_len);
        if try!(sock.take(arr_len as u64).read_to_end(&mut buf_copy)) != arr_len {
            return Err(Error::Disconnected);
        };

        offset = 12;
        sig = "a(yv)".to_string();
        let header_fields = match try!(demarshal(&mut buf_copy, &mut offset, &mut sig)) {
            Value::Array(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        msg.headers = HashMap::new();
        for i in header_fields.objects {
            let mut st = match i {
                Value::Struct(x) => x,
                x => panic!("Demarshal didn't return what we asked for: {:?}", x)
            };
            let val = st.objects.remove(1);
            let code = DBusDecoder::decode::<u8>(st.objects.remove(0)).unwrap();
            msg.headers.insert(code, val);
        }

        // Read the padding, if any
        let trailing_pad = 8 - (offset % 8);
        if trailing_pad % 8 != 0 {
            try!(read_exactly(sock, &mut buf, trailing_pad));
        }

        // Finally, read the entire body
        if body_len > 0 {
            let v = match msg.headers.get(&(HeaderFieldName::Signature as u8)) {
                Some(&Value::Variant(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let sigval = match v.object.deref() {
                &Value::BasicValue(BasicValue::Signature(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let mut body = Vec::new();
            try!(read_exactly(sock, &mut body, body_len as usize));

            let mut sig = "(".to_string() + &sigval.0 + ")";
            offset = 0;
            let objs = match try!(demarshal(&mut body, &mut offset, &mut sig)) {
                Value::Struct(x) => x.objects,
                x => panic!("Didn't get a struct: {:?}", x)
            };
            for x in objs {
                msg.body.push(x);
            }
        }

        Ok(msg)
    }
}

#[test]
fn test_connect () {
    let mut conn = Connection::connect_uds("/var/run/dbus/system_bus_socket").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    let resp = conn.call_sync(&mut msg).unwrap();
    println!("ListNames: {:?}", resp);
}

#[cfg(tcp)]
#[test]
fn test_tcp () {
    let mut conn = Connection::connect_tcp("localhost:12345").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    conn.send(&mut msg).ok();
    let msg = conn.read_msg().unwrap();
    println!("{:?}", msg.body);
    //loop {
    //    conn.read_msg().unwrap();
    //}
}
<|endoftext|>


<commit_before>extern crate libc;
use self::libc::{c_char, c_int};
use std::ffi::{CString, CStr};
use std::str::from_utf8;

#[link(name = "resolv")]
extern {
    pub fn __res_query(dname: *const c_char, class: c_int, typef: c_int,
               answer: *const u8, anslen: c_int) -> c_int;
}

#[test]
fn query() {
    let dname = CString::new("_leader._tcp.mesos").unwrap();
    let ans: *const u8 = 0 as *const u8;
    let class: c_int = 33;
    let typef: c_int = 33;
    unsafe {
        let r = __res_query(dname.as_ptr(), class, typef,
                           ans, 1);
        println!("res_query -> {:?}", r);
    }
}
<commit_msg>Add some dns stuff<commit_after>extern crate libc;
use self::libc::{c_char, c_int};
use std::ffi::{CString, CStr};
use std::str::from_utf8;

#[derive(PartialEq,Debug,Clone)]
pub enum Type {
	// valid dnsRR_Header.Rrtype and dnsQuestion.qtype
	A     = 1,
	NS    = 2,
	MD    = 3,
	MF    = 4,
	CNAME = 5,
	SOA   = 6,
	MB    = 7,
	MG    = 8,
	MR    = 9,
	NULL  = 10,
	WKS   = 11,
	PTR   = 12,
	HINFO = 13,
	MINFO = 14,
	MX    = 15,
	TXT   = 16,
	AAAA  = 28,
	SRV   = 33,

	// valid dnsQuestion.qtype only
	AXFR  = 252,
	MAILB = 253,
	MAILA = 254,
	ALL   = 255,
}

#[derive(PartialEq,Debug,Clone)]
pub enum Class {
	// valid dnsQuestion.qclass
	INET   = 1,
	CSNET  = 2,
	CHAOS  = 3,
	HESIOD = 4,
	ANY    = 255,
}

#[derive(PartialEq,Debug,Clone)]
pub enum Rcode {
	// dnsMsg.rcode
	Success        = 0,
	FormatError    = 1,
	ServerFailure  = 2,
	NameError      = 3,
	NotImplemented = 4,
	Refused        = 5,
}

#[link(name = "resolv")]
extern {
    pub fn __res_query(dname: *const c_char, class: c_int, typef: c_int,
               answer: *const u8, anslen: c_int) -> c_int;
}

fn query(dname: &str, class: Class, typef: Type) -> Result<&str, Rcode> {
    let dname = CString::new("_leader._tcp.mesos").unwrap();
    let ans: *const u8 = &[0u8;1024] as *const u8;
    println!("ans addr is {:?}", ans);
    unsafe {
        let r = __res_query(dname.as_ptr(), 1, 33,
                           ans, 1024);
        println!("res_query -> {:?}", r);
    }
    Err(Rcode::NotImplemented)
}

#[test]
fn test_query() {
    let r = query("_leader._tcp.mesos", Class::INET, Type::SRV);
    println!("result: {:?}", r);
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::str::FromStr;

use num::NumCast;

use super::{File, Value};

/// An interface for converting from `Value` variants.
pub trait FromValue: Sized {
    /// Returns `Some` if the conversion was successful, `None` otherwise.
    fn from_value(value: &Value) -> Option<Self>;
}

impl FromValue for Value {
    fn from_value(value: &Value) -> Option<Self> {
        Some(value.clone())
    }
}

macro_rules! num_from_value {
    ($ty:ty) => {
        /// Casts from any of the numeric variants (`I64`, `U64`, `F64`) and converts from the
        /// `String` variant using `std::str::FromStr`.
        impl FromValue for $ty {
            fn from_value(value: &Value) -> Option<$ty> {
                match *value {
                    Value::I64(value) => NumCast::from(value),
                    Value::U64(value) => NumCast::from(value),
                    Value::F64(value) => NumCast::from(value),
                    Value::String(ref value) => FromStr::from_str(value).ok(),
                    _ => None,
                }
            }
        }
    }
}

num_from_value!(u8);
num_from_value!(u16);
num_from_value!(u32);
num_from_value!(u64);
num_from_value!(usize);
num_from_value!(i8);
num_from_value!(i16);
num_from_value!(i32);
num_from_value!(i64);
num_from_value!(isize);
num_from_value!(f32);
num_from_value!(f64);

/// Converts from any of the flat variants (`Null`, `Boolean`, `I64`, `U64`, `F64`, `String`).
///
/// `Null` is converted to an empty string. All other variants make use of `std::string::ToString`,
/// so the respective `Display` formatted results are used. For example, `Boolean` values are
/// converted into either `"false"` or `"true"`.
impl FromValue for String {
    fn from_value(value: &Value) -> Option<String> {
        match *value {
            Value::Null => Some(String::new()),
            Value::Boolean(value) => Some(value.to_string()),
            Value::I64(value) => Some(value.to_string()),
            Value::U64(value) => Some(value.to_string()),
            Value::F64(value) => Some(value.to_string()),
            Value::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }
}

static FALSE_STRINGS: &'static [&'static str] = &["0", "f", "F", "false", "FALSE", "off", "OFF"];
static TRUE_STRINGS: &'static [&'static str] = &["1", "t", "T", "true", "TRUE", "on", "ON"];

/// Converts from common representations of `false` and `true`.
///
/// * `Boolean` values are mapped directly.
/// * `I64` and `U64` map `0` and `1` to `false` and `true` respectively.
/// * `String` maps `"0"`, `"f"`, `"F"`, `"false"`, `"FALSE"`, `"off"`, and `"OFF"` to `false`.
/// * `String` maps `"1"`, `"t"`, `"T"`, `"true"`, `"TRUE"`, `"on"`, and `"ON"` to `true`.
/// * All other variants return `None`.
impl FromValue for bool {
    fn from_value(value: &Value) -> Option<bool> {
        match *value {
            Value::Boolean(value) => Some(value),
            Value::I64(value) if value == 0 => Some(false),
            Value::I64(value) if value == 1 => Some(true),
            Value::U64(value) if value == 0 => Some(false),
            Value::U64(value) if value == 1 => Some(true),
            Value::String(ref value) if FALSE_STRINGS.contains(&&value[..]) => Some(false),
            Value::String(ref value) if TRUE_STRINGS.contains(&&value[..]) => Some(true),
            _ => None,
        }
    }
}

/// Extracts from `File` variant.
impl FromValue for File {
    fn from_value(value: &Value) -> Option<File> {
        match *value {
            Value::File(ref file) => Some(file.clone()),
            _ => None,
        }
    }
}

/// Converts the `Null` variant to `None` and delegates any other variants to `T::from_value`.
impl<T: FromValue> FromValue for Option<T> {
    fn from_value(value: &Value) -> Option<Option<T>> {
        match *value {
            Value::Null => Some(None),
            _ => T::from_value(value).map(|result| Some(result)),
        }
    }
}

/// Converts from `Array` variant.
impl<T: FromValue> FromValue for Vec<T> {
    fn from_value(value: &Value) -> Option<Vec<T>> {
        match *value {
            Value::Array(ref array) => {
                let mut vec = Vec::with_capacity(array.len());
                for value in array {
                    match T::from_value(value) {
                        Some(value) => vec.push(value),
                        None => return None,
                    }
                }
                Some(vec)
            },
            _ => None,
        }
    }
}

/// Converts using `Map::to_strict_map` if the variant is `Map`, returns `None` otherwise.
impl<T: FromValue> FromValue for BTreeMap<String, T> {
    fn from_value(value: &Value) -> Option<BTreeMap<String, T>> {
        match *value {
            Value::Map(ref map) => map.to_strict_map(),
            _ => None,
        }
    }
}
<commit_msg>Add tests for regressive number casting behavior<commit_after>use std::collections::BTreeMap;
use std::str::FromStr;

use num::NumCast;

use super::{File, Value};

/// An interface for converting from `Value` variants.
pub trait FromValue: Sized {
    /// Returns `Some` if the conversion was successful, `None` otherwise.
    fn from_value(value: &Value) -> Option<Self>;
}

impl FromValue for Value {
    fn from_value(value: &Value) -> Option<Self> {
        Some(value.clone())
    }
}

macro_rules! num_from_value {
    ($ty:ty) => {
        /// Casts from any of the numeric variants (`I64`, `U64`, `F64`) and converts from the
        /// `String` variant using `std::str::FromStr`.
        impl FromValue for $ty {
            fn from_value(value: &Value) -> Option<$ty> {
                match *value {
                    Value::I64(value) => NumCast::from(value),
                    Value::U64(value) => NumCast::from(value),
                    Value::F64(value) => NumCast::from(value),
                    Value::String(ref value) => FromStr::from_str(value).ok(),
                    _ => None,
                }
            }
        }
    }
}

num_from_value!(u8);
num_from_value!(u16);
num_from_value!(u32);
num_from_value!(u64);
num_from_value!(usize);
num_from_value!(i8);
num_from_value!(i16);
num_from_value!(i32);
num_from_value!(i64);
num_from_value!(isize);
num_from_value!(f32);
num_from_value!(f64);

/// Converts from any of the flat variants (`Null`, `Boolean`, `I64`, `U64`, `F64`, `String`).
///
/// `Null` is converted to an empty string. All other variants make use of `std::string::ToString`,
/// so the respective `Display` formatted results are used. For example, `Boolean` values are
/// converted into either `"false"` or `"true"`.
impl FromValue for String {
    fn from_value(value: &Value) -> Option<String> {
        match *value {
            Value::Null => Some(String::new()),
            Value::Boolean(value) => Some(value.to_string()),
            Value::I64(value) => Some(value.to_string()),
            Value::U64(value) => Some(value.to_string()),
            Value::F64(value) => Some(value.to_string()),
            Value::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }
}

static FALSE_STRINGS: &'static [&'static str] = &["0", "f", "F", "false", "FALSE", "off", "OFF"];
static TRUE_STRINGS: &'static [&'static str] = &["1", "t", "T", "true", "TRUE", "on", "ON"];

/// Converts from common representations of `false` and `true`.
///
/// * `Boolean` values are mapped directly.
/// * `I64` and `U64` map `0` and `1` to `false` and `true` respectively.
/// * `String` maps `"0"`, `"f"`, `"F"`, `"false"`, `"FALSE"`, `"off"`, and `"OFF"` to `false`.
/// * `String` maps `"1"`, `"t"`, `"T"`, `"true"`, `"TRUE"`, `"on"`, and `"ON"` to `true`.
/// * All other variants return `None`.
impl FromValue for bool {
    fn from_value(value: &Value) -> Option<bool> {
        match *value {
            Value::Boolean(value) => Some(value),
            Value::I64(value) if value == 0 => Some(false),
            Value::I64(value) if value == 1 => Some(true),
            Value::U64(value) if value == 0 => Some(false),
            Value::U64(value) if value == 1 => Some(true),
            Value::String(ref value) if FALSE_STRINGS.contains(&&value[..]) => Some(false),
            Value::String(ref value) if TRUE_STRINGS.contains(&&value[..]) => Some(true),
            _ => None,
        }
    }
}

/// Extracts from `File` variant.
impl FromValue for File {
    fn from_value(value: &Value) -> Option<File> {
        match *value {
            Value::File(ref file) => Some(file.clone()),
            _ => None,
        }
    }
}

/// Converts the `Null` variant to `None` and delegates any other variants to `T::from_value`.
impl<T: FromValue> FromValue for Option<T> {
    fn from_value(value: &Value) -> Option<Option<T>> {
        match *value {
            Value::Null => Some(None),
            _ => T::from_value(value).map(|result| Some(result)),
        }
    }
}

/// Converts from `Array` variant.
impl<T: FromValue> FromValue for Vec<T> {
    fn from_value(value: &Value) -> Option<Vec<T>> {
        match *value {
            Value::Array(ref array) => {
                let mut vec = Vec::with_capacity(array.len());
                for value in array {
                    match T::from_value(value) {
                        Some(value) => vec.push(value),
                        None => return None,
                    }
                }
                Some(vec)
            },
            _ => None,
        }
    }
}

/// Converts using `Map::to_strict_map` if the variant is `Map`, returns `None` otherwise.
impl<T: FromValue> FromValue for BTreeMap<String, T> {
    fn from_value(value: &Value) -> Option<BTreeMap<String, T>> {
        match *value {
            Value::Map(ref map) => map.to_strict_map(),
            _ => None,
        }
    }
}

#[test]
fn cast_within_bounds() {
    assert_eq!(<u8 as FromValue>::from_value(&Value::U64(100)), Some(100));
    assert_eq!(<u8 as FromValue>::from_value(&Value::String("100".to_owned())), Some(100));
    assert_eq!(<i8 as FromValue>::from_value(&Value::I64(-100)), Some(-100));
    assert_eq!(<i8 as FromValue>::from_value(&Value::String("-100".to_owned())), Some(-100));
}

#[test]
fn cast_out_of_bounds() {
    assert!(<u8 as FromValue>::from_value(&Value::U64(1000)).is_none());
    assert!(<u8 as FromValue>::from_value(&Value::String("1000".to_owned())).is_none());
    assert!(<i8 as FromValue>::from_value(&Value::I64(-1000)).is_none());
    assert!(<i8 as FromValue>::from_value(&Value::String("-1000".to_owned())).is_none());
}
<|endoftext|>


<commit_before>use super::ToTokens;

use std::iter;

use proc_macro2::{TokenStream, TokenTree};

/// TokenStream extension trait with methods for appending tokens.
///
/// This trait is sealed and cannot be implemented outside of the `quote` crate.
pub trait TokenStreamExt: private::Sealed {
    fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>;

    fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>;

    fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens;

    fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens;
}

impl TokenStreamExt for TokenStream {
    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.extend(iter::once(token.into()));
    }

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # extern crate proc_macro2;
    /// # use quote::{TokenStreamExt, ToTokens};
    /// # use proc_macro2::TokenStream;
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

mod private {
    use proc_macro2::TokenStream;

    pub trait Sealed {}

    impl Sealed for TokenStream {}
}
<commit_msg>Move TokenStreamExt documentation to trait methods<commit_after>use super::ToTokens;

use std::iter;

use proc_macro2::{TokenStream, TokenTree};

/// TokenStream extension trait with methods for appending tokens.
///
/// This trait is sealed and cannot be implemented outside of the `quote` crate.
pub trait TokenStreamExt: private::Sealed {
    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>;

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # extern crate proc_macro2;
    /// # use quote::{TokenStreamExt, ToTokens};
    /// # use proc_macro2::TokenStream;
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>;

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens;

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens;
}

impl TokenStreamExt for TokenStream {
    fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.extend(iter::once(token.into()));
    }

    fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

mod private {
    use proc_macro2::TokenStream;

    pub trait Sealed {}

    impl Sealed for TokenStream {}
}
<|endoftext|>


<commit_before>use libc::c_char;

#[repr(C)]
pub enum nfdresult_t {
    NFD_ERROR,
    NFD_OKAY,
    NFD_CANCEL
}

#[link(name = "nfd")]
extern {
    pub fn NFD_OpenDialog(filter_list: *const c_char, default_path: *const c_char, outPath: *mut *mut c_char) -> nfdresult_t;
    pub fn NFD_SaveDialog(filter_list: *const c_char, default_path: *const c_char, outPath: *mut *mut c_char) -> nfdresult_t;

    pub fn NFD_GetError() -> *const c_char;
}
<commit_msg>Add #[allow(dead_code)] for nfdresult_t<commit_after>use libc::c_char;

#[allow(dead_code)]
#[repr(C)]
pub enum nfdresult_t {
    NFD_ERROR,
    NFD_OKAY,
    NFD_CANCEL
}

#[link(name = "nfd")]
extern {
    pub fn NFD_OpenDialog(filter_list: *const c_char, default_path: *const c_char, outPath: *mut *mut c_char) -> nfdresult_t;
    pub fn NFD_SaveDialog(filter_list: *const c_char, default_path: *const c_char, outPath: *mut *mut c_char) -> nfdresult_t;

    pub fn NFD_GetError() -> *const c_char;
}
<|endoftext|>